티스토리 뷰
지난 포스팅까지해서 Form을 통한 로그인은 구현을 해봤습니다. 완벽하다고는 할 수 없으나 사용하기엔 충분하리라 생각합니다. 하지만 저의 최종 Goal은 Rest Application이므로 로그인도 Rest 방식으로 변경을 해보겠습니다.
. antMatchers(HttpMethod.OPTIONS, "/**").permitAll() : 크롬과 같은 브라우저에서는 실제 GET, POST 요청을 하기 전에 OPTIONS를 preflight 요청합니다. 이는 실제 서버가 살아있는지를 사전에 확인하는 요청입니다. Spring에서는 OPTIONS에 대한 요청을 막고 있으므로 해당 코드를 통해서 OPTIONS 요청이 왔을 때도 오류를 리턴하지 않도록 해줍니다. 마지막으로 rest 방식으로 할 경우 Cross Domain 문제가 발생할 수 있습니다. 이는 기본적으로 타 도메인간(포트만 다를지라도)에는 javascript 요청을 할 수 없도록 되어 있기 때문입니다. 이를 해결하기 위한 표준으로 CORS가 있습니다. CORS Filter를 적용함으로써 해결을 할 수 있습니다. Filter를 구현해서 SimplCorsFilter 클래스를 만들어 줍니다. . Filter는 스프링에서 제공하는 기능은 아니고 Servlet에서 정의한 명세입니다. 이를 @Component로 정의해서 Bean으로 등록해줍니다. . 허용되는 Origin(도메인)과 메소드 방식, Header를 정의해서 리턴해줍니다. 위와 같은 코드를 작성함으로써 모든 도메인에 모든 요청을 받을 수 있게 해줍니다.package com.cusonar.example.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.session.web.http.HeaderHttpSessionStrategy;
import org.springframework.session.web.http.HttpSessionStrategy;
import com.cusonar.example.user.service.UserService;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/user/login").permitAll()
.antMatchers("/user").hasAuthority("USER")
.antMatchers("/admin").hasAuthority("ADMIN")
.anyRequest().authenticated()
.and()
// .formLogin()
// .and()
.logout()
;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService)
.passwordEncoder(userService.passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
package com.cusonar.example.user.controller;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.cusonar.example.user.domain.AuthenticationRequest;
import com.cusonar.example.user.domain.AuthenticationToken;
import com.cusonar.example.user.domain.User;
import com.cusonar.example.user.service.UserService;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired AuthenticationManager authenticationManager;
@Autowired UserService userService;
@RequestMapping(value="/login", method=RequestMethod.POST)
public AuthenticationToken login(
@RequestBody AuthenticationRequest authenticationRequest,
HttpSession session
) {
String username = authenticationRequest.getUsername();
String password = authenticationRequest.getPassword();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
User user = userService.readUser(username);
return new AuthenticationToken(user.getName(), user.getAuthorities(), session.getId());
}
}
package com.cusonar.example.user.domain;
public class AuthenticationRequest {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.cusonar.example.user.domain;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
public class AuthenticationToken {
private String username;
private Collection extends GrantedAuthority> authorities;
private String token;
public AuthenticationToken(String username, Collection extends GrantedAuthority> collection, String token) {
this.username = username;
this.authorities = collection;
this.token = token;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Collection extends GrantedAuthority> getAuthorities() {
return authorities;
}
public void setAuthorities(Collection
package com.cusonar.example.user;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.cusonar.example.ExampleApplication;
import com.cusonar.example.user.domain.AuthenticationRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@WebAppConfiguration
public class UserControllerTest {
@Autowired private WebApplicationContext wac;
private MockMvc mvc;
@Before
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(wac)
.build();
}
@Test
public void loginTest() throws Exception {
AuthenticationRequest request = new AuthenticationRequest();
request.setUsername("user1");
request.setPassword("pass1");
ObjectMapper om = new ObjectMapper();
mvc.perform(post("/user/login")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(om.writeValueAsString(request)))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.username", is(request.getUsername().toUpperCase())))
.andExpect(jsonPath("$.authorities[*].authority", hasItem("USER")))
;
}
}
package com.cusonar.example.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.session.web.http.HeaderHttpSessionStrategy;
import org.springframework.session.web.http.HttpSessionStrategy;
import com.cusonar.example.user.service.UserService;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests()
.antMatchers("/user/login").permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/user").hasAuthority("USER")
.antMatchers("/admin").hasAuthority("ADMIN")
.anyRequest().authenticated()
.and()
// .formLogin()
// .and()
.logout()
;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService)
.passwordEncoder(userService.passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public HttpSessionStrategy httpSessionStrategy() {
return new HeaderHttpSessionStrategy();
}
}
package com.doosan.ddms.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCorsFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-auth-token, content-type");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
'Java > Spring Boot' 카테고리의 다른 글
Spring boot 파일 다운로드 (0) | 2019.05.17 |
---|---|
Spring boot 파일 업로드 (0) | 2019.05.16 |
7. Spring Boot Security 4편 - 그 외 기능들 (0) | 2016.06.12 |
6. Spring Boot Security 3편 - 패스워드 암호화 (7) | 2016.06.12 |
4-1(번외). MyBatis의 TypeHandler를 이용해 GrantedAuthority 바로 받기 (3) | 2016.06.10 |
- Total
- Today
- Yesterday
- 알고리즘
- 빠른 정렬
- controller test
- routing
- styleUrls
- Spring Boot
- spring security
- 유아동겸용
- angular 2
- 어드보케이트
- mockmvc
- 타보유모차
- templateUrl
- routeParams
- Ajax
- angular
- test static import
- 기내반입유모차
- CURL
- TypeScript
- 티지유모차
- insert sort
- 거품정렬
- routerLink
- rest login
- router-outlet
- RouteConfig
- mybatis
- angular2
- 머지소트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |