HTTP状态403 - 在请求参数上找到无效的CSRF令牌“null” [英] HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter

查看:547
本文介绍了HTTP状态403 - 在请求参数上找到无效的CSRF令牌“null”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须向我的restful服务发出HTTP.Post(Android应用程序),以注册新用户!

I have to issue a HTTP.Post (Android App) to my restful service, to register a new user!

问题是,当我尝试发布时对寄存器端点的请求(没有安全性),Spring一直阻止我!

The problem is, when I try to issue a request to a register endpoint ( without security ), Spring keeps blocking me!

我的项目依赖性

<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>

Spring Security

Spring Security

<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>

控制器

@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(Angular)

JS Post ( Angular )

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

错误

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'

---解决方案---

实施过滤器,将我的X-XSRF-TOKEN附加到每个请求header

Implemented a filter to attach my X-XSRF-TOKEN to every request header

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

在web.xml中添加了此过滤器的映射并完成了!

Added a mapping to this filter to the web.xml and done!

推荐答案

在上面的代码中,我看不到会将CSRF令牌传递给客户端的内容(如果你使用JSP等,它是自动的。)。

In your code above, I can't see something which would pass the CSRF token to the client (which is automatic if you use JSP etc.).

一种流行的做法是编写一个过滤器,将CSRF令牌作为cookie附加。然后,您的客户端首先发送GET请求以获取该cookie。对于后续请求,该cookie随后将作为标头发回。

A popular practice for this is to code a filter to attach the CSRF token as a cookie. Your client then sends a GET request first to fetch that cookie. For the subsequent requests, that cookie is then sent back as a header.

而官方 Spring Angular guide 详细说明,你可以参考 Spring Lemon 是一个完整的工作示例。

Whereas the official Spring Angular guide explains it in details, you can refer to Spring Lemon for a complete working example.

要将cookie作为标题发回,您可能需要编写一些代码。 AngularJS默认情况下这样做(除非你发送跨域请求),但这里有一个例子,如果你的客户没有这样做会有帮助:

For sending the cookie back as a header, you may need to write some code. AngularJS by default does that (unless you are sending cross-domain requests), but here is an example, if it would help in case your client doesn't:

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');

    }]);

这篇关于HTTP状态403 - 在请求参数上找到无效的CSRF令牌“null”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆