2015-05-29 12 views
17

Utilizzo Spring Social Facebook all'interno di un progetto Spring MVC per supportare l'accesso a Facebook. Funziona bene in quasi tutti i casi, ma occasionalmente vedo la seguente eccezione nei log.Spring Social Facebook: "Il parametro OAuth2" stato "non corrisponde"

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) 

non sono stato in grado di capire quando ciò si verifica, e non sono stato in grado di riprodurla, ma ho visto che ciò accada per gli altri utenti piuttosto un paio di volte. Di seguito è la mia configurazione di Facebook sociale di primavera.

@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; 
    } 
} 

Perché ciò si verifica e cosa posso fare per impedirlo? Grazie.

risposta

2

Questa funzione genera semplicemente un valore di stato String (per impostazione predefinita UUID.randomUUID().toString()), lo inserisce nella sessione e lo passa al provider come parametro "stato" nella richiesta di autorizzazione. Si prevede che il provider lo riporti sulla richiamata. Se lo stato memorizzato corrisponde a quello nella richiamata, allora siamo a posto. Se non corrispondono, è quando vedi l'eccezione che hai menzionato lì.

Questo dovrebbe funzionare, ma sì, vedo che ci sono problemi qui. Ho anche trovato questo collegamento che potrebbe valere la pena dare un'occhiata: https://github.com/spring-projects/spring-social-facebook/issues/103

+0

Grazie per la vostra spiegazione.Non so ancora in quali scenari i valori non corrispondono. In precedenza avevo già esaminato il problema, ma sembrava che Facebook lo avesse risolto, quindi non ci pensavo più. – Andy0708

+0

Si è verificato un problema con un parametro stato nullo. Uso Spring Social. Ci devo fare qualcosa di sbagliato con la mia configurazione. Ho aperto una discussione qui: http://stackoverflow.com/q/39469165/536299 Qualcuno può aiutarmi? – balteo

7

Il parametro state impedisce gli attacchi CSRF in OAuth2.

L'essere un'idea:

  • La vostra applicazione aggiunge un parametro state alla richiesta che fa al server di autenticazione (in questo caso, Facebook)
  • Il server di autenticazione fa eco il valore esatto di quel state parametro di nuovo a voi nella risposta
  • È quindi controllare per vedere se corrispondono fino

Sembra inutile ... ma impedisce agli aggressori di effettuare richieste di azione della tua app client che non è stata avviata.

Questo copre in grande dettaglio:

http://www.twobotechnologies.com/blog/2014/02/importance-of-state-in-oauth2.html

Primavera Sociale gestisce tutto questo per voi: la generazione di un nuovo caso state per ogni richiesta, e il tentativo automaticamente in base al valore nella risposta.

Quindi non si può impedire che:, e non si desidera: questi potrebbero essere veri e propri tentativi di attacco falliti - e in quei casi, si desidera questo errore accadere.

Per i casi che hai postato, è potrebbe essere la gestione buggy del parametro state da Spring Social o dai server di autenticazione di Facebook.

Ma, da parte tua, è necessario gestire l'eccezione, come se si trattasse di un tentativo di attacco vero e proprio: il login avvisi/persone di allarme/ecc

+0

Grazie per la spiegazione. Capisco lo scopo del parametro 'state' e, come dici tu, non sono davvero interessato a rimuoverlo. Proverò a indagare ulteriormente. Grazie ancora. – Andy0708

Problemi correlati