login API에서 매개변수로 HttpServletResponse를 받는게 이해가 가지 않아 동기분이 설명을 해주셨는데 그 내용을 정리하려한다.
HttpServletResponse res
토큰을 login에서 만드는데 HttpServletRequest가 아닌 HttpServletResponse에서 받는 이유는 무엇인가?
-> 토큰을 만드는데 HttpServletResponse을 사용하는 것이 아니라 만든 토큰을 담는 용도로 실제 토큰을 만들때는 username을 사용함
@PostMapping("/login")
public ResponseEntity<MsgResponseDto> login(@RequestBody LoginRequestDto loginRequestDto , HttpServletResponse res){
try{
userService.login(loginRequestDto, res);
} catch (NoSuchElementException e){
return ResponseEntity.badRequest().body(new MsgResponseDto("닉네임 또는 패스워드를 확인해주세요."));
}
return ResponseEntity.ok().body(new MsgResponseDto("로그인 성공"));
}
login 기능을 controller에 만들어도 상관은 없으나 Filter에 포함하여 최초에 진행하는 방법이 좋음
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
-- 생략 --
* login URL 설정
http.formLogin((formLogin) ->
formLogin
.loginPage("/api/user/login-page").permitAll()
);
* 사용하는 필터 추가
http.addFilterBefore(jwtAuthorizationFilter(), JwtAuthenticationFilter.class);
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
2.JwtAuthenticationFilter
=> login을 위한 class
=> 기존 과제파일에서는 JwtUtil, JwtAuthorizationFilter만 있었음
@Slf4j(topic = "JWT 검증 및 인가")
public class JwtAuthorizationFilter extends OncePerRequestFilter {
private final JwtUtil jwtUtil;
private final UserDetailsServiceImpl userDetailsService;
public JwtAuthorizationFilter(JwtUtil jwtUtil, UserDetailsServiceImpl userDetailsService) {
this.jwtUtil = jwtUtil;
this.userDetailsService = userDetailsService;
}
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws ServletException, IOException {
String tokenValue = jwtUtil.getJwtFromHeader(req);
if (StringUtils.hasText(tokenValue)) {
if (!jwtUtil.validateToken(tokenValue)) {
log.error("Token Error");
return;
}
Claims info = jwtUtil.getUserInfoFromToken(tokenValue);
try {
setAuthentication(info.getSubject());
} catch (Exception e) {
log.error(e.getMessage());
return;
}
}
filterChain.doFilter(req, res);
}
// 인증 처리
public void setAuthentication(String username) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication = createAuthentication(username);
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
}
// 인증 객체 생성
private Authentication createAuthentication(String username) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
}
}