2015-08-13 23 views
5

Devo rilasciare un HTTP.Post (app Android) al mio servizio restful, per registrare un nuovo utente!Stato HTTP 403 - È stato trovato il token CSRF "null" non valido sul parametro di richiesta

Il problema è che quando provo a inviare una richiesta a un endpoint di registro (senza sicurezza), Spring continua a bloccarmi!

mio progetto Dipendenze

<properties> 
    <java-version>1.6</java-version> 
    <org.springframework-version>4.1.7.RELEASE</org.springframework-version> 
    <org.aspectj-version>1.6.10</org.aspectj-version> 
    <org.slf4j-version>1.6.6</org.slf4j-version> 
    <jackson.version>1.9.10</jackson.version> 
    <spring.security.version>4.0.2.RELEASE</spring.security.version> 
    <hibernate.version>4.2.11.Final</hibernate.version> 
    <jstl.version>1.2</jstl.version> 
    <mysql.connector.version>5.1.30</mysql.connector.version> 
</properties> 

Primavera di sicurezza

<beans:beans xmlns="http://www.springframework.org/schema/security" 
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd 
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security.xsd"> 

<!--this is the register endpoint--> 
<http security="none" pattern="/webapi/cadastro**"/> 


    <http auto-config="true" use-expressions="true"> 
       <intercept-url pattern="/webapi/dados**" 
      access="hasAnyRole('ROLE_USER','ROLE_SYS')" /> 
     <intercept-url pattern="/webapi/system**" 
      access="hasRole('ROLE_SYS')" /> 

<!--  <access-denied-handler error-page="/negado" /> --> 
     <form-login login-page="/home/" default-target-url="/webapi/" 
      authentication-failure-url="/home?error" username-parameter="username" 
      password-parameter="password" /> 
     <logout logout-success-url="/home?logout" />   
     <csrf token-repository-ref="csrfTokenRepository" /> 
    </http> 

    <authentication-manager> 
     <authentication-provider> 
      <password-encoder hash="md5" /> 
      <jdbc-user-service data-source-ref="dataSource" 
       users-by-username-query="SELECT username, password, ativo 
        FROM usuarios 
        WHERE username = ?" 
       authorities-by-username-query="SELECT u.username, r.role 
        FROM usuarios_roles r, usuarios u 
        WHERE u.id = r.usuario_id 
        AND u.username = ?" /> 
     </authentication-provider> 
    </authentication-manager> 

    <beans:bean id="csrfTokenRepository" 
     class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository"> 
     <beans:property name="headerName" value="X-XSRF-TOKEN" /> 
    </beans:bean> 

</beans:beans> 

controller

@RestController 
@RequestMapping(value="/webapi/cadastro", produces="application/json") 
public class CadastroController { 
    @Autowired 
    UsuarioService usuarioService; 

    Usuario u = new Usuario(); 

    @RequestMapping(value="/novo",method=RequestMethod.POST) 
    public String register() { 
     // this.usuarioService.insert(usuario); 
     // usuario.setPassword(HashMD5.criptar(usuario.getPassword())); 
     return "teste"; 
    } 
} 

JS Post (angolare)

$http.post('/webapi/cadastro/novo').success(function(data) { 
      alert('ok'); 
     }).error(function(data) { 
      alert(data); 
     }); 

e l'errore

HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN' 

--- --- Soluzione

implementato un filtro per collegare il mio X-XSRF-token per ogni richiesta di intestazione

public class CsrfHeaderFilter extends OncePerRequestFilter { 
    @Override 
    protected void doFilterInternal(HttpServletRequest request, 
     HttpServletResponse response, FilterChain filterChain) 
     throws ServletException, IOException { 
    CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class 
     .getName()); 
    if (csrf != null) { 
     Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN"); 
     String token = csrf.getToken(); 
     if (cookie==null || token!=null && !token.equals(cookie.getValue())) { 
     cookie = new Cookie("XSRF-TOKEN", token); 
     cookie.setPath("/"); 
     response.addCookie(cookie); 
     } 
    } 
    filterChain.doFilter(request, response); 
    } 
} 

Aggiunto una mappatura a questo filtro per il web.xml e fatto!

risposta

11

Nel codice sopra riportato, non riesco a vedere qualcosa che possa passare il token CSRF al client (che è automatico se si utilizza JSP ecc.).

Una pratica comune per questo è codificare un filtro per collegare il token CSRF come cookie. Il tuo cliente quindi invia prima una richiesta GET per recuperare quel cookie. Per le richieste successive, quel cookie viene quindi restituito come intestazione.

Mentre lo Spring Angular guide ufficiale lo spiega nei dettagli, è possibile fare riferimento a Spring Lemon per un esempio operativo completo.

Per l'invio del cookie come intestazione, potrebbe essere necessario scrivere del codice. AngularJS lo fa per impostazione predefinita (a meno che tu non invii richieste tra domini), ma qui è un esempio, se sarebbe di aiuto nel caso in cui il tuo cliente non:

angular.module('appBoot') 
    .factory('XSRFInterceptor', function ($cookies, $log) { 

    var XSRFInterceptor = { 

     request: function(config) { 

     var token = $cookies.get('XSRF-TOKEN'); 

     if (token) { 
      config.headers['X-XSRF-TOKEN'] = token; 
      $log.info("X-XSRF-TOKEN: " + token); 
     } 

     return config; 
     } 
    }; 
    return XSRFInterceptor; 
    }); 

angular.module('appBoot', ['ngCookies', 'ngMessages', 'ui.bootstrap', 'vcRecaptcha']) 
    .config(['$httpProvider', function ($httpProvider) { 

     $httpProvider.defaults.withCredentials = true; 
     $httpProvider.interceptors.push('XSRFInterceptor'); 

    }]); 
Problemi correlati