JWT Login 시, accessToken이 null
Environment
Language: Java
DB: MySQL
오류
private Claims parseClaims(ServletRequest request) {
String accessToken = SecurityUtils.resolveToken((HttpServletRequest) request);
if(accessToken == null)
return null;
Key secretKey = Keys.hmacShaKeyFor(JWT_SECRET.getBytes(StandardCharsets.UTF_8));
return Jwts.parserBuilder()
.setSigningKey(secretKey)
.build()
.parseClaimsJws(accessToken)
.getBody();
}
Header Type, Request Body의 데이터가 정확함에도 accessToken이 null
원인
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
// 1. Request Header에서 JWT 토큰 추출
Authentication authentication = jwtTokenProvider.getAuthentication(request);
// 2. 토큰 유효성 검사
// 토큰이 유효할 경우, 토큰에서 Authentication 객체를 가지고 와서 SecurityContext에 저장
if (authentication != null && jwtTokenProvider.isValidToken(request)) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
// 현재 필터가 요청을 처리한 후, 필터 체인의 다음 필터로 요청과 응답을 전달
}
SpringSecurity와 JWT가 동작하는 과정
- 애플리케이션 시작 → Spring Security의 초기화 및 설정 과정(Filter 등)
- API 호출 → JwtAuthenticationFilter 요청 처리
필터 통과: 요청을 다음 필터로 전달
필터 통과 X: 오류 반환 - 필터 체인을 모두 통과한 요청은 Controller로 전달
- Controller → UserService 호출
- UserService에서 AuthenticationManager은 UserDetailsService 호출
- AuthenticationManagerBuilder 동작
- AuthenticationManagerBuilder에서 사용자가 제공한 정보(이메일과 비밀번호)를 확인
* 사용자가 입력한 이메일과 비밀번호를 담은 인증 토큰 생성 - AuthenticationManagerBuilder에서 authentificate() 호출하여 인증 시도
내부적으로 CustomUserDetailsService의 loadUserByUsername() 호출
*주어진 이메일로 데이터베이스에서 사용자를 찾아서 그 정보를 UserDetails 객체로 반환 - AuthenticationManagerBuilder에서 6과 7의 객체 비교
* 인증 성공: Authentication 객체는 SecurityContext에 저장, 이후의 요청에서 사용자 정보를 참조할 수 있음
* 인증 실패: BadCredentialsException 발생 - UserService에서 JwtTokenProvider의 generateToken() 호출
JwtAuthenticationFilter 처리 시, 모든 요청에 대해 getAuthentification() 동작
→ 로그인 시에는 token이 없어 Header에 token을 넣고 요청할 수 없음
→ accessToken이 null
⭐ Controller 처리 전에 오류가 발생, Controller에서 디버그해도 넘어오지 않음⭐
해결
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
String accessToken = SecurityUtils.resolveToken(request);
if (accessToken != null && jwtTokenProvider.isValidToken(request)) {
Authentication authentication = jwtTokenProvider.getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
getAuthentification()이 아닌 토큰을 추출하는 메서드(resolveToken())를 수행
→ null이 아닐 때 getAuthentification() 수행
'Java > Spring with Error' 카테고리의 다른 글
[해결 방법] NoUniqueBeanDefinitionException (0) | 2024.09.04 |
---|---|
[해결방법] io.jsonwebtoken.ExpiredJwtException (0) | 2024.08.30 |
[해결 방법] Could not find javax.servlet:jstl (0) | 2023.10.03 |
[해결 방법] org.gradle.api.GradleScriptException (0) | 2023.08.27 |
[해결 방법] java.lang.IllegalStateException (0) | 2023.08.22 |