스프링 MVC 로그인 구현
• 스프링 시큐리티 필터에 의존하는 대신 수동으로 사용자를 인증하는 경우
스프링 MVC 컨트롤러 엔드포인트를 사용할 수 있다
• 요청 간에 인증을 저장하고 싶다면 HttpSessionSecurityContextRepository 를 사용하여 인증 상태를 저장 할 수있다
@RestController
@RequiredArgsConstructor
public class LoginController {
private final AuthenticationManager authenticationManager;
private final HttpSessionSecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();
@PostMapping("/login")
public Authentication login(@RequestBody LoginRequest login, HttpServletRequest request, HttpServletResponse response) {
// UsernamePasswordAuthenticationToken token =
// new UsernamePasswordAuthenticationToken(login.getUsername(),login.getPassword()) -> 이런식으로 해도 되고,아래처럼 해도된다.
UsernamePasswordAuthenticationToken token =
UsernamePasswordAuthenticationToken.unauthenticated(login.getUsername(), login.getPassword()); // 인증 객체생성
Authentication authentication = authenticationManager.authenticate(token); // 인증 성공시 새로운 인증객체[인증된 상태의 객체] 반환, 실패시 예외 발생
SecurityContext securityContext = SecurityContextHolder.getContextHolderStrategy().createEmptyContext(); // SecurityContext 객체생성
securityContext.setAuthentication(authentication);// SecurityContext에 인증객체 저장
SecurityContextHolder.getContextHolderStrategy().setContext(securityContext);
// ThreadLocal에 SecurityContext 저장, 해당 요청에서는 ThreadLocal에서 인증객체를 꺼내서 처리하는 로직이 없어 이 코드가 필요하지는 않지만
// 추가적으로 로직상 인증객체를 꺼내서 사용해야한다면 이렇게 저장해서 사용한다.
securityContextRepository.saveContext(securityContext,request,response);
// 인증상태를 유지하기위해 securityContextRepository를 이용하여 세션에 SecurityContext를 저장한다.
return authentication;
}
}
Spring Security는 기본적으로 인증 정보를 세션에 자동으로 저장하므로 따로 저장하는 코드를 사용할 필요는 없다.
[자동으로 저장하지않도록 설정할 수도 있다.]
@Data
public class LoginRequest {
private String username;
private String password;
}
@EnableWebSecurity
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/login").permitAll()
.anyRequest().authenticated())
// .formLogin(Customizer.withDefaults());
.csrf(csrf -> csrf.disable());
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
@Bean
public UserDetailsManager userDetailsManager() {
UserDetails user = User.withUsername("user")
.password("{noop}1234")
.authorities("ROLE_USER")
.build();
UserDetails user2 = User.withUsername("user2")
.password("{noop}1234")
.authorities("ROLE_USER")
.build();
UserDetails user3 = User.withUsername("user3")
.password("{noop}1234")
.authorities("ROLE_USER")
.build();
return new InMemoryUserDetailsManager(user, user2, user3);
}
}
.formLogin()을 주석처리하지않는다면 /login의 request를 필터에서 formLogin이 가로채기때문에 login API가 동작하지않을것이다.
login api의 엔드포인트를 바꾸거나 formLogin을 주석처리하던가 해야한다.
포스트맨으로 요청해서 테스트해도 되지만 다음과 같이 인텔리제이에서도 요청가능하다.
https://ksh-coding.tistory.com/97
옆에 Examples를 이용하여 요청 샘플을 받아 사용하면된다.
login.http
POST https://localhost:8080/login
Content-Type: application/json
{
"username": "user",
"password": "1111"
}
다음과 같은 결과를 확인할 수 있다.
'인프런 > 스프링 시큐리티 완전 정복 [6.x 개정판]' 카테고리의 다른 글
14) 세션관리 - SessionManagementFilter / ConcurrentSessionFilter (2) | 2024.10.23 |
---|---|
13)세션관리 - 동시 세션 제어 , 세션 고정 보호, 세션 생성 정책 (1) | 2024.10.22 |
11) 인증 상태 영속성 - SecurityContextRepository & SecurityContextHolderFilter (1) | 2024.10.18 |
10) 사용자 상세 서비스 - UserDetailsService , 사용자 상세 -UserDetails (1) | 2024.10.17 |
9) 인증 제공자 - AuthenticationProvider (1) | 2024.10.16 |
댓글