이전 글에 이어서 2번째 시간이다. 정말 너무나도 많이 security가 변화했기 때문에 물러날 곳이 없다. 블로그에도 많은 자료들이 있지 않고 정말 docs를 통해서만 봐야한다. 진짜 물러날 곳이 없지만 앞으로 쭉쭉쭉 가야한다.
만약 이곳에 본인이 찾던 문제가 없었다면? 이전글을 확인해주세요!
SpringSecurity deprecated 된 것들이 왤케 많아? 시즌 1
이제 하나씩 어떻게 해결이 되게 되었는지 확인해보자.
이거 관련하여서 해결하는데 docs를 꼼꼼히 살펴볼 필요가 있었다. 아래 코드에서 오류는 다음과 같이 나타난다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
return http.authorizeHttpRequests(authz -> authz
.requestMatchers("/login", "/signup", "/user").permitAll()
.anyRequest().authenticated()
).formLogin((formLogin) ->
formLogin.loginPage("/login")
.defaultSuccessUrl("/articles")
).logout((logout) ->
logout.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
)
.csrf(AbstractHttpConfigurer::disable)
.build();
}
This method cannot decide whether these patterns are Spring MVC patterns or not.
If this endpoint is a Spring MVC endpoint, please userequestMatchers(MvcRequestMatcher)
;
otherwise, please userequestMatchers(AntPathRequestMatcher)
.
이 문제에 대해서 여러가지 샘플들을 제공해주고 있다! 꼭 이곳을 들어가서 다른 deprecated 되거나 버전 관련 문제가 있다면 살펴보자!
오류에 나와있는 것처럼 requestMatchers(MvcRequestMatcher)
;
otherwise, please use requestMatchers(AntPathRequestMatcher)
. 이런 형태로 작성하여야 한다는 것이다.
mvc를 사용했다면 MvcRequestMatcher
를 이용해서 이런식으로 사용하고
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
http.authorizeHttpRequests((requests) -> requests
.requestMatchers(mvcMatcherBuilder.pattern("/test1")).permitAll()
.anyRequest().authenticated()
);
return http.build();
}
아니라면 AntPathRequestMatcher
를 이용해서 다음과 같이 사용해야 한다.
@Bean
public WebSecurityCustomizer configure(){
return (web) -> web.ignoring()
.requestMatchers(toH2Console())
.requestMatchers(AntPathRequestMatcher.antMatcher("/static/**"));
}
그래서 위와 같은 방법을 사용하여 이전의 코드에서 다음과 같이 변경하니 문제가 해결이 되었다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception{
MvcRequestMatcher.Builder mvc = new MvcRequestMatcher.Builder(introspector);
return http.authorizeHttpRequests(authz -> authz
.requestMatchers(mvc.pattern("/login"), mvc.pattern("/signup"), mvc.pattern("/user")).permitAll()
.anyRequest().authenticated()
).formLogin((formLogin) ->
formLogin.loginPage("/login")
.defaultSuccessUrl("/articles")
).logout((logout) ->
logout.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
)
.csrf(AbstractHttpConfigurer::disable)
.build();
}
보통 같으면 다음과 같이 실습에서 따라하라고 예제가 나올거다.
@Bean
public AuthenticationManager authenticationManager(HttpSecurity http, BCryptPasswordEncoder bCryptPasswordEncoder, UserDetailService userDetailService) throws Exception{
return http.getSharedObject(AuthenticationManagerBuilder.class)
.userDetailsService(userDetailService)
.passwordEncoder(bCryptPasswordEncoder)
.and().build();
}
그렇지만? 이렇게 진행하면 이전 글에서 언급했던 것처럼 and가 deprecated되어서 람다식을 사용해야하기 때문에 다른 방법을 모색해야한다. 그래서 찾다보니 이곳에서는 다음과 같은 방식을 사용하는 것을 추천한다.
https://stackoverflow.com/questions/74877743/spring-security-6-0-dao-authentication
@Bean
public AuthenticationManager authenticationManager() throws Exception{
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailService);
authProvider.setPasswordEncoder(bCryptPasswordEncoder());
return new ProviderManager(authProvider);
}
이 그림을 보면서 얘기를 해보자.
위 코드처럼 바뀌어도 결국 의도는 같다. 여기에 처음 만들게 되는 DaoAuthenticationProvider
로 인증 개체를 만들게 되어 이를 기반으로 사용자 인증을 시도한다.
그래서 위 처음 보이게 되었던 코드가 거의 솔루션을 제공했던 코드와 같이 변경이 되어진다.
@Bean
public AuthenticationManager authenticationManager() throws Exception{
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailService);
authProvider.setPasswordEncoder(bCryptPasswordEncoder());
return new ProviderManager(authProvider);
}
실력이 쭉쭉쭉 docs를 보면서 늘어간다는 생각으로 계속 확인해야겠다. 실제로도 보면서 읽는 방법을 계속 익혀가는거 같다는 것이 중요한 것이다.
이후에 또 3편이 아마... 나오게 될 거 같은 건 기분 탓일까?