[SPRING] Spring Social Facebook : "OAuth2 'state'매개 변수가 일치하지 않습니다."
SPRINGSpring Social Facebook : "OAuth2 'state'매개 변수가 일치하지 않습니다."
Spring MVC 프로젝트 내에서 Spring Social Facebook을 사용하여 Facebook 로그인을 지원하고 있습니다. 이것은 거의 모든 경우에 잘 작동하지만 때로는 로그에 다음 예외가 표시됩니다.
ERROR org.springframework.social.connect.web.ProviderSignInController - Exception while completing OAuth 2 connection:
java.lang.IllegalStateException: The OAuth2 'state' parameter doesn't match.
at org.springframework.social.connect.web.ConnectSupport.verifyStateParameter(ConnectSupport.java:173)
at org.springframework.social.connect.web.ConnectSupport.completeConnection(ConnectSupport.java:155)
at org.springframework.social.connect.web.ProviderSignInController.oauth2Callback(ProviderSignInController.java:216)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:168)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.example.something.CorsFilter.doFilter(CorsFilter.java:49)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:673)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:516)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1086)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:659)
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1558)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1515)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
이 문제가 언제 발생하는지 파악할 수 없었지만 재현 할 수 없었지만 다른 사용자에게 몇 번이나 발생하는 것을 보았습니다. 아래는 내 Spring Social Facebook 구성입니다.
@Configuration
public class SocialConfig {
@Bean
public ProviderSignInController providerSignInController() {
ProviderSignInController controller = new ProviderSignInController(this.connectionFactoryLocator(), this.usersConnectionRepository(), new SpringSecuritySignInAdapter(this.accountRepository));
controller.addSignInInterceptor(new RedirectToPreviousPageInterceptor(controller, this.analyticsService));
return controller;
}
@Bean
public ConnectionFactoryRegistry connectionFactoryLocator() {
ConnectionFactoryRegistry connectionFactoryRegistry = new ConnectionFactoryRegistry();
List<ConnectionFactory<?>> connectionFactories = new ArrayList<ConnectionFactory<?>>();
connectionFactories.add(this.facebookConnectionFactory());
connectionFactoryRegistry.setConnectionFactories(connectionFactories);
return connectionFactoryRegistry;
}
@Bean
public FacebookConnectionFactory facebookConnectionFactory() {
FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory(this.facebookAppId, this.facebookAppSecret);
connectionFactory.setScope(this.scope);
return connectionFactory;
}
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public Facebook facebook(ConnectionRepository repository) {
Connection<Facebook> connection = repository.findPrimaryConnection(Facebook.class);
return (connection != null ? connection.getApi() : null);
}
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public ConnectionRepository connectionRepository() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
}
Account account = (Account) authentication.getPrincipal();
return this.usersConnectionRepository().createConnectionRepository(String.valueOf(account.getId()));
}
@Bean
public JdbcUsersConnectionRepository usersConnectionRepository() {
JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(this.dataSource, this.connectionFactoryLocator(), this.textEncryptor);
repository.setConnectionSignUp(this.accountService);
return repository;
}
}
왜 이런 일이 발생하며, 이것을 막기 위해 무엇을 할 수 있습니까? 감사.
해결법
-
==============================
1.상태 매개 변수는 OAuth2에서 CSRF 공격을 방지합니다.
상태 매개 변수는 OAuth2에서 CSRF 공격을 방지합니다.
아이디어는 :
그것은 무의미한 것으로 들리지만 공격자가 시작하지 않은 클라이언트 앱 작업 요청을하지 못하게합니다.
이 부분은 매우 자세히 다룹니다.
http://www.twobotechnologies.com/blog/2014/02/importance-of-state-in-oauth2.html
Spring Social은 모든 요구 사항에 대해 새로운 임의의 상태를 생성하고 자동으로 응답의 값과 일치 시키려고 시도하는 모든 것을 처리합니다.
그래서 당신은 그것을 막을 수 없습니다 : 그리고 당신은 원하지 않습니다 : 이것은 진짜 실패한 공격 시도 일 수 있습니다 - 그리고 그러한 경우에, 당신은이 오류가 일어나길 원합니다.
게시 한 경우 Spring Social 또는 Facebook의 인증 서버에 의한 상태 매개 변수의 처리가 버그가있을 수 있습니다.
하지만, 여러분의 입장에서 보면, 실제 공격 시도처럼 예외를 처리해야합니다 : 경고 / 경고 사람들 / 등.
-
==============================
2.이 함수는 상태 값 문자열 (기본적으로 UUID.randomUUID (). toString ())을 생성하고 세션에 배치 한 다음 권한 요청의 "상태"매개 변수로 공급자에게 전달합니다. 공급자는 콜백으로 다시 전달할 것으로 예상됩니다. 저장된 상태가 콜백의 상태와 일치하면 우리는 좋습니다. 만약 그들이 일치하지 않는다면, 당신이 여기서 언급 한 예외를 보게 될 것입니다.
이 함수는 상태 값 문자열 (기본적으로 UUID.randomUUID (). toString ())을 생성하고 세션에 배치 한 다음 권한 요청의 "상태"매개 변수로 공급자에게 전달합니다. 공급자는 콜백으로 다시 전달할 것으로 예상됩니다. 저장된 상태가 콜백의 상태와 일치하면 우리는 좋습니다. 만약 그들이 일치하지 않는다면, 당신이 여기서 언급 한 예외를 보게 될 것입니다.
이것은 단지 작동해야하지만, 네, 여기에 문제가 있다는 것을 알았습니다. 나는 또한 가치가 있을지도 모른다이 연결을 찾아 냈다 : https://github.com/spring-projects/spring-social-facebook/issues/103
from https://stackoverflow.com/questions/30526748/spring-social-facebook-the-oauth2-state-parameter-doesnt-match by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 애플리케이션 컨텍스트 이벤트를 다른 컨텍스트로 연결하는 방법 (0) | 2019.04.16 |
---|---|
[SPRING] Mockito @ InjectMocks는 어떻게 작동합니까? (0) | 2019.04.15 |
[SPRING] 클래스 값을 Spring bean 속성으로 설정하는 방법은 무엇입니까? (0) | 2019.04.15 |
[SPRING] 스프링 부트 프로젝트에서 CSS와 같은 정적 파일을 어디에 둘까요? (0) | 2019.04.15 |
[SPRING] @Configuration 클래스의 주석으로 구동되는 트랜잭션 설정하기 (0) | 2019.04.15 |