728x90
먼저 이 문제는 '스프링 부트와 AWS로 혼자 구현하는 웹 서비스'라는 책을 실습하는 과정에서 마주친 상황이다.
책은 몇 년 전에 지어진 기준이라 자바나 스프링부트의 버전이 낮게 되어있다. 그렇지만 그 당시 버전보다는 지금 상황에서 안정된 최신 버전으로 변경사항은 고치며 해보고 싶어 최신버전으로 진행했다.
- Spring Boot : 3.1.2
- Java : 17
- Gradle : 8.2.1
spring-security-config : 6.1.2
우선 책에서는
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final CustomOAuth2UserService customOAuth2UserService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.headers().frameOptions().disable()
.and()
.authorizeRequests()
.antMatchers("/", "/css/**", "/images/**", "/js/**", "/h2-console/**", "/profile").permitAll()
.antMatchers("/api/v1/**").hasRole(Role.USER.name())
.anyRequest().authenticated()
.and()
.logout()
.logoutSuccessUrl("/")
.and()
.oauth2Login()
.userInfoEndpoint()
.userService(customOAuth2UserService);
}
}
이렇게 구성되어 있었다.
Deprecated List (spring-security-docs 6.1.3 API)
Authorize HttpServletRequests :: Spring Security
공식문서를 참고해서 deprecated된 것을 알맞게 나름 수정해 봤다.
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig {
private final CustomOAuth2UserService customOAuth2UserService;
@Bean
protected SecurityFilterChain configure(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.headers((headers) -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/css/**", "/images/**", "/js/**", "/h2-console/**", "/profile").permitAll()
.requestMatchers("/api/v1/**").hasRole(Role.USER.name())
.anyRequest().authenticated())
.logout((logout) -> logout
.logoutSuccessUrl("/"))
.oauth2Login((oauth2) -> oauth2
.userInfoEndpoint(userInfoEndpoint -> userInfoEndpoint
.userService(customOAuth2UserService)))
return http.build();
}
}
문제 상황
우선 security가 제대로 작동하지 않는 것 같았다. `permitAll()`을 사용해서 지정된 경로를 들어갔을 때는 인증을 요구하지 않게 했는데도 자꾸 로그인으로 자동으로 redirect 됐다. 그래서 공식문제 예제들을 보니 `@Configuration`이 있다는 것을 확인했다. (책의 예제는 왜 없는지 모르겠다.. )
`@Configuration`을 사용하니 아예 에러를 내보냈는데
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0: Error creating bean with name 'configure' defined in class path resource [com/hoya/studying/springbootwebservice/config/auth/SecurityConfig.class]: Failed to instantiate [org.springframework.security.web.SecurityFilterChain]: Factory method 'configure' threw exception with message: This method cannot decide whether these patterns are Spring MVC patterns or not. If this endpoint is a Spring MVC endpoint, please use requestMatchers(MvcRequestMatcher); otherwise, please use requestMatchers(AntPathRequestMatcher).
이 글을 참고하면 해결할 수 있다.
해결
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final CustomOAuth2UserService customOAuth2UserService;
@Bean
protected SecurityFilterChain configure(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.headers((headers) -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable))
.authorizeHttpRequests(auth -> auth
.requestMatchers(
new AntPathRequestMatcher("/"),
new AntPathRequestMatcher("/css/**"),
new AntPathRequestMatcher("/images/**"),
new AntPathRequestMatcher("/js/**"),
new AntPathRequestMatcher("/h2-console/**"),
new AntPathRequestMatcher("/profile")
).permitAll()
.requestMatchers(new AntPathRequestMatcher("/api/v1/**")).hasRole(Role.USER.name())
.anyRequest().authenticated())
.logout((logout) -> logout
.logoutSuccessUrl("/"))
.oauth2Login((oauth2) -> oauth2
.userInfoEndpoint(userInfoEndpoint -> userInfoEndpoint
.userService(customOAuth2UserService))
.defaultSuccessUrl("/", true));
return http.build();
}
}
서버를 시작하고 맨 처음에 로그인을 성공하면 자체적으로 설정한 파비콘 링크로 리다이렉트가 돼서 defaultSuccessUrl을 true로 해서 무조건 "/"로 가게 설정했다.
언제나 잘못된 설명이나 부족한 부분에 대한 피드백은 환영입니다🤍
728x90