작성
·
3K
0
안녕하세요 강사님. 저는 아래와 같이 하였는데 null 에러가 나서 질문드려요. 소스도 공유합니다.
깃헙 : https://github.com/DongWoonKim/core-spring-security-ajax
@Bean
AuthenticationManager authenticationManager1 (HttpSecurity http) throws Exception {
return http.getSharedObject(AuthenticationManager.class);
}
http
.addFilterBefore(new AjaxLoginProcessingFilter() , UsernamePasswordAuthenticationFilter.class );
error message
{
"timestamp": "2022-09-28T12:58:47.088+00:00",
"status": 500,
"error": "Internal Server Error",
"trace": "java.lang.NullPointerException: Cannot invoke \"org.springframework.security.authentication.AuthenticationManager.authenticate(org.springframework.security.core.Authentication)\" because the return value of \"com.example.corespringsecurityajax.security.filter.AjaxLoginProcessingFilter.getAuthenticationManager()\" is null\n\tat com.example.corespringsecurityajax.security.filter.AjaxLoginProcessingFilter.attemptAuthentication(AjaxLoginProcessingFilter.java:39)\n\tat org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:227)\n\tat org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)\n\tat org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103)\n\tat org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)\n\tat org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)\n\tat org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)\n\tat org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:112)\n\tat org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:82)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)\n\tat org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)\n\tat org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346)\n\tat org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221)\n\tat org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186)\n\tat org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)\n\tat org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n\tat org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n\tat org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n\tat org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)\n\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)\n\tat org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)\n\tat org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)\n\tat org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)\n\tat org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789)\n\tat org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)\n\tat org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)\n\tat org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)\n\tat java.base/java.lang.Thread.run(Thread.java:833)\n",
"message": "Cannot invoke \"org.springframework.security.authentication.AuthenticationManager.authenticate(org.springframework.security.core.Authentication)\" because the return value of \"com.example.corespringsecurityajax.security.filter.AjaxLoginProcessingFilter.getAuthenticationManager()\" is null",
"path": "/api/login"
}
답변 2
1
네
그건 HttpSecurity 빈으로 생성되는 시점에서는 AuthenticationManager 가 아직 HttpSecurity 의 공유객체로 저장이 되지 않았기 때문입니다.
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
HttpSecurity httpSecurity() throws Exception {
WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
this.context);
AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
this.objectPostProcessor, passwordEncoder);
authenticationBuilder.parentAuthenticationManager(authenticationManager());
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
// @formatter:off
http
.csrf(withDefaults())
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling(withDefaults())
.headers(withDefaults())
.sessionManagement(withDefaults())
.securityContext(withDefaults())
.requestCache(withDefaults())
.anonymous(withDefaults())
.servletApi(withDefaults())
.apply(new DefaultLoginPageConfigurer<>());
http.logout(withDefaults());
// @formatter:on
applyDefaultConfigurers(http);
return http;
}
위의 코드는 HttpSecurity 가 빈으로 생성되는 구문인데
AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
this.objectPostProcessor, passwordEncoder);
authenticationBuilder.parentAuthenticationManager(authenticationManager());
코드를 보시면 AuthenticationManagerBuilder 를 생성하고 공유객체로 설정하고 있습니다.
그런데 AuthenticationManager 를 별도로 HttpSecurity 의 공유객체로 설정하는 구문은 없고
AuthenticationManagerBuilder 의 parent 속성에만 저장하고 있습니다.
그리고 AuthenticationManagerBuilder 클래스도 AuthenticationManager 를 참조할 수 있는 메소드를 제공하고 있지 않습니다.
그렇기 때문에 http.getSharedObject(AuthenticationManager.class); 를 실행하면 AuthenticationManager 가 null 값으로 나오게 됩니다.
저도 HttpSecurity 에서 초기화시 생성된 AuthenticationManager 객체와 동일한 객체를 참조할 수 있는 방법이 있는지 다각도로 살펴 보았지만 아직 발견하지 못했습니다.
그런데 AuthenticationManager 는 아예 새롭게 생성해서 사용해도 크게 문제될 것은 없습니다.
가령 예를 들어서
ProviderManager providerManager = new ProviderManager();
List<AuthenticationProvider> providers = providerManager.getProviders();
providers.add(new DaoAuthenticationProvider());
providers.add(new AnonymousAuthenticationProvider("key"));
providers.add(new CustomAuthenticationProvider());
CutomAuthenticationFilter cutomAuthenticationFilter = new CustomAuthenticationFilter();
cutomAuthenticationFilter.setAuthenticationManager(providerManager);
http.addFilterBefore(cutomAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
이렇게 해도 실행하는데는 문제가 없습니다.
다만 스프링 시큐리티가 생성한 ProviderManager 객체와 커스텀하게 생성한 ProviderManager 를 어떤 필터에서 사용할 것인지를 잘 결정해야 하고 설정해 주어야 합니다.
일단
@Bean AuthenticationManager authenticationManager(AuthenticationConfiguration authConfiguration) throws Exception { return authConfiguration.getAuthenticationManager(); }
이렇게 사용하시는 것을 권해 드립니다.
0
어떤 식으로 해결하셨나요? 공유된 깃 허브에 @Bean AuthenticationManager authenticationManager1 (HttpSecurity http) throws Exception { return http.getSharedObject(AuthenticationManager.class); } 부분을 넣어서 실행했는데 똑같이 매니저 null 오류가 나네요..