어제 jwt 하려고 세팅까지 해놨다가 오늘 토큰 발급까지 완료했다.
SecurityConfig에서 달라진 게 있다면,,
1. http.addFilter()로 필터 적용해주기
2. 세션을 사용하지 않으므로 .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
로 stateless 서버로 설정해주기
3. 기본 폼 로그인 비활성화
4. http 기본 인증 비활성화
@Bean
public CorsFilter corsFilter(){
// 특정 URL 패턴에 대한 CORS 설정을 등록하기 위한 소스
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration(); // CORS 정책을 정의하는 객체
config.setAllowCredentials(true); // 클라이언트 측에서 자바스크립트를 통해 응답을 처리할 수 있도록 설정
config.addAllowedOrigin("*"); // 모든 ip에 응답 허용
config.addAllowedHeader("*"); // 모든 header에 응답 허용
config.addAllowedMethod("*"); // 모든 post, get, put, delete, patch 요청 허용
// 특정 URL 패턴(/api/**)에 대해 위에서 정의한 CORS 설정을 등록
source.registerCorsConfiguration("/api/**", config);
// 새로운 CorsFilter 객체를 생성하고 반환 -> 해당 필터는 스프링 시큐리티 필터 체인에 추가되어 CORS 규칙을 적용
return new CorsFilter(source);
}
// 스프링 시큐리티에서 UsernamePasswordAuthenticationFilter 존재
// /login 요청해서 username, password 전송하면(post)
// UsernamePasswordAuthenticationFilter 동작함
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
private final JwtUtil jwtUtil;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtUtil jwtUtil) {
this.authenticationManager = authenticationManager;
this.jwtUtil = jwtUtil;
}
// /login 요청을 하면 로그인 시도를 위해서 실행되는 함수
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
System.out.println("JwtAuthenticationFilter 로그인 시도 중");
// 1. username, pw 받아서
try {
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(request.getInputStream(), User.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
// 정상인지 로그인 시도. AuthenticationManager로 로그인(인증) 시도
// PrincipalDetailsService의 loadUserByUsername() 함수가 실행된 후, 정상이면 authentication이 리턴됨
Authentication authentication = authenticationManager.authenticate(token);
// 로그인이 정상적으로 되면 PrincipalDetails 객체를 얻음
PrincipalDetails principalDetails = (PrincipalDetails) authentication.getPrincipal();
System.out.println("로그인 완료됨 : " + principalDetails.getUser());
// authentication 객체가 session영역에 저장을 해야하고 그 방법이 return 해주면 됨
// 리턴의 이유는 권한 관리를 security가 대신 해주기 때문에 편하려고 하는거임
// 굳이 JWT 토큰을 사용하면서 세션을 만들 이유가 없음. 근데 단지 권한 처리 때문에 session 넣어줌
return authentication;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// attemptAuthentication 실행 후 인증이 정상적으로 되었으면 실행
// JWT 토큰을 만들어서 request 요청한 사용자에게 JWT 토큰을 response 해주면 됨
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authentication) throws IOException, ServletException {
System.out.println("successfulAuthentication 실행 -> 인증 완료");
// 인증된 사용자 정보를 PrincipalDetails 객체에서 가져옴
PrincipalDetails principalDetails = (PrincipalDetails) authentication.getPrincipal();
// JWT 토큰 생성
String jwtToken = jwtUtil.createToken(principalDetails.getUser().getUsername());
// 응답 헤더에 생성된 JWT 토큰을 추가
response.addHeader("Authorization", "Bearer " + jwtToken);
}
}
이렇게 추가해주면
저런 식으로 헤더에 Authorization이 새롭게 추가된 걸 볼 수 있다..!.!
테스트라 그냥 아무 키나 넣고 생성함ㅎㅎ