jwt토큰을 이용한 로그인을 구현중에 발생한 실수이다.
분명 로그인시에 jwt토큰을 발급하고 postman을 이용해 유저가 서버에 정보를 요청할때 그 토큰을 같이 보냈다.
그런데 계속 Security context에서 유저에 대한 정보를 가져올 때 annonymousUser라고 뜨며 유저에 대한 정보를 받아오지 못했다.
java.util.NoSuchElementException: No value present
그래서 원인을 찾아보았다.
원인은 전에 테스트로 잠깐 쓰던 config파일이였다.
package com.ll.medium.global.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class ApiSecurityConfig {
@Bean
SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception{
http
.securityMatcher("/api/**","/**","http://localhost:5173")
.csrf(
csrf-> csrf.disable()
).cors(
cors->cors.configure(http)
);
return http.build();
}
}
package com.ll.medium.global.security;
import com.ll.medium.global.jwt.JwtAccessDeniedHandler;
import com.ll.medium.global.jwt.JwtAuthenticationEntryPoint;
import com.ll.medium.global.jwt.JwtFilter;
import com.ll.medium.global.jwt.TokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final TokenProvider tokenProvider;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
// PasswordEncoder는 BCryptPasswordEncoder를 사용
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// token을 사용하는 방식이기 때문에 csrf를 disable합니다.
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(
sessionManagement ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.exceptionHandling(exceptionHandling ->
exceptionHandling
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)
)
// enable h2-console
.headers(headers ->
headers
.frameOptions(frameOptions ->
frameOptions
.sameOrigin()
)
)
.authorizeHttpRequests(request ->
request.requestMatchers("/api/authenticate","/api/member/join","/favicon.ico")
.permitAll()
.requestMatchers(PathRequest.toH2Console()).permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(
new JwtFilter(tokenProvider),
UsernamePasswordAuthenticationFilter.class); // JwtFilter를 addFilterBefore로 등록했던 JwtSecurityConfig class 적용
return httpSecurity.build();
}
}
원래는 밑의 파일이 실행되면서 JwtFilter가 filterchain에 추가되어 토큰의 정보를 받은후에 올바른 토큰인지에 대한 확인후 유저정보를 받아줘야 하지만 전에 쓰던 위의 파일을 지우지 않아 밑의 파일이 적용되지 않았던것 같다.
이 실수를 코드의 흐름을 보다가 JwtFilter가 제대로 적용되지 않는다는 점을 찾아 실수를 찾을 수 있었다....