简体   繁体   English

HTTP状态403 - 在请求参数'_csrf'或标题'X-CSRF-TOKEN'上找到无效的CSRF令牌'9ee6949c-c5dc-4d4b-9d55-46b75abc2994'

[英]HTTP Status 403 - Invalid CSRF Token '9ee6949c-c5dc-4d4b-9d55-46b75abc2994' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'

I am developing a web application which has a front-end with angularjs and a back-end with spring-security and jersey. 我正在开发一个Web应用程序,它有一个带有angularjs的前端和一个带有弹簧安全和平针织物的后端。

I am trying to implement spring-security. 我正在努力实现spring-security。 I can authenticate the user. 我可以验证用户身份。 But I stucked at the logout point. 但我坚持退出点。 I am sending the X-CSRF-TOKEN within a value, but it seems that spring-security is refusing it. 我在一个值内发送X-CSRF-TOKEN,但似乎spring-security拒绝它。

web.xml web.xml中

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>


    <display-name>M2Carros</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:applicationContext.xml
            classpath:spring-security.xml
        </param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>
            com.sun.jersey.spi.spring.container.servlet.SpringServlet
        </servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>br.com.m2carros</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
            <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
            <param-value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

<!--    Spring Security -->
    <filter>
        <filter-name>

    springSecurityFilterChain</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy

</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
        <init-param>
            <param-name>cors.allowed.headers</param-name>
            <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization</param-value>
        </init-param> 
        <init-param>
            <param-name>cors.exposed.headers</param-name>
            <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization,X-CSRF-TOKEN</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CorsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

spring-security.xml 弹簧security.xml文件

<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-3.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <!-- enable use-expressions -->
    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/" access="permitAll" />
        <intercept-url pattern="/index.html" access="permitAll" />
        <intercept-url pattern="/api/user" access="isAuthenticated()" />
        <!-- enable csrf protection -->
        <csrf/>
    </http>

    <!-- Select users and user_roles from database -->
    <authentication-manager>
        <authentication-provider>
<!--            <password-encoder hash="md5" />  -->
            <jdbc-user-service data-source-ref="dataSource"
                users-by-username-query=
                    "select username,password, enabled from usuario where username=?"
                authorities-by-username-query=
                    "select username, role from user_roles where username =?  " />
        </authentication-provider>
    </authentication-manager>

</beans:beans>

app.js (ommited routes) app.js(ommited routes)

$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
    var csrfHeaderName = 'X-CSRF-TOKEN';

    $httpProvider.interceptors.push(function() {
        return {
            response: function(response) {
                console.log(response.headers());
                console.log(response.headers(csrfHeaderName));
                if(response.headers(csrfHeaderName) != null){
                    $httpProvider.defaults.headers.common[csrfHeaderName] = response.headers(csrfHeaderName);
                }
                return response;
            }
        }    
    });

appCtrl.js appCtrl.js

angular.module('m2App').controller('appCtrl', function($rootScope, $scope, $http, $location){

    var serverUrl = 'http://localhost:8080/m2carros/api';

    var authenticate = function(credentials, callback) {

        var headers = credentials ? {authorization : "Basic "
            + btoa(credentials.username + ":" + credentials.password)
        } : {};

        $http.get(serverUrl+'/user', {headers : headers}).then(function(response) {
          if (response.data.principal != undefined && response.data.principal.username) {
            $rootScope.authenticated = true;
            console.log("is authenticated ? "+$rootScope.authenticated);
          } else {
            $rootScope.authenticated = false;
            console.log("is authenticated ? "+$rootScope.authenticated);
          }
          callback && callback();
        }, function() {
          $rootScope.authenticated = false;
          console.log("is authenticated ? "+$rootScope.authenticated);
          callback && callback();
        });

      }


      authenticate();
      $scope.credentials = {};
      $scope.login = function() {
          authenticate($scope.credentials, function() {
            if ($rootScope.authenticated) {
              $location.path("/");
              console.log("Redirecionando usuario autenticado para /")
              self.error = false;
            } else {
              $location.path("/login");
              self.error = true;
            }
          });
      };

      $rootScope.logout = function() {
          $http.post('logout', {}).then(function() {
            $rootScope.authenticated = false;
            $location.path("/");
          });
        }

});

Authenticating User 验证用户

Trying to Logout 试图退出

XSRF is a technique by which an unauthorized site can gain your user's private data. XSRF是一种未经授权的站点可以获取用户私有数据的技术。 Angular provides a mechanism to counter XSRF. Angular提供了一种对抗XSRF的机制。 When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). 执行XHR请求时,$ http服务从cookie(默认情况下为XSRF-TOKEN)读取令牌,并将其设置为HTTP头(X-XSRF-TOKEN)。

If you set appropriate cookie, then it ensures that angular will take care of the header internally 如果你设置了适当的cookie,那么它确保angular将在内部处理标题

So on that case, you need to check that server config won't need a new token each request 因此,在这种情况下,您需要检查服务器配置是否每个请求都不需要新的令牌

You need to send the csrf token when you submit your form. 您需要在提交表单时发送csrf令牌。 You need to add the following line in your HTML form: 您需要在HTML表单中添加以下行:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

Resource Link: 资源链接:

  1. Spring Rest Service - Invalid CSRF token when I attempt to login Spring Rest Service - 尝试登录时无效的CSRF令牌

As CodeMed suggested to add 正如CodeMed建议补充的那样

.antMatchers("/send-pin").permitAll()

in SecurityConfiguration class. SecurityConfiguration类中。 He got some issue as stated below: 他遇到了一些问题,如下所述:

To examine the Network tab of the Firefox debug tools, which showed that the following two cookies were sent with the request: JSESSIONID:"99192501E7CEA0EDEF853BD666AF3C35" and XSRF-TOKEN:"b50afb87-e15c-4bef-93ca-7c2fdf145fd8", even though the server log for the same request still boiled down to Invalid CSRF token found for http://localhost:9000/send-pin . 要检查Firefox调试工具的“网络”选项卡,其中显示以下两个cookie随请求一起发送:JSESSIONID:“99192501E7CEA0EDEF853BD666AF3C35”和XSRF-TOKEN:“b50afb87-e15c-4bef-93ca-7c2fdf145fd8”,即使服务器对于同一请求的日志仍然归结为为http:// localhost:9000 / send-pin找到的无效CSRF令牌。 This caused me to examine why the sent token was being rejected, and a few minutes later I noticed the missing antmatchers(...) for the url pattern, leading to this answer. 这导致我检查发送令牌被拒绝的原因,几分钟后我注意到url模式缺少的antmatchers(...),导致这个答案。

This change caused SecurityConfiguration.configure(...) method to now look like: 此更改导致SecurityConfiguration.configure(...)方法现在看起来像:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().and().authorizeRequests()
        .antMatchers("/send-pin").permitAll() 
        .antMatchers("/check-pin").permitAll()
        .antMatchers("/index.html", "/", "/login", "/someotherrurl") 
        .permitAll().anyRequest().authenticated().and().csrf()
        .csrfTokenRepository(csrfTokenRepository()).and()
        .addFilterAfter(csrfHeaderFilter(), CsrfFilter.class);
}  

Resource Link: 资源链接:

  1. How do I send CSRF tokens from AngularJS front end to Spring REST service backend? 如何从AngularJS前端向Spring REST服务后端发送CSRF令牌?
  2. Spring Security - Token based API auth & user/password authentication Spring Security - 基于令牌的API身份验证和用户/密码身份验证

For those who are facing the same problem. 对于那些面临同样问题的人。 Here is my solution. 这是我的解决方案。

  1. First I wasn't able to get the cookie using $cookies.get(). 首先,我无法使用$ cookies.get()获取cookie。 It's because that the cookie that I was returning from the backend didn't had a path configured. 这是因为我从后端返回的cookie没有配置路径。
  2. After the authentication where I get a token I make many other http requests and I was discarding the tokens returned by these requests. 在我获得令牌的身份验证之后,我发出了许多其他的http请求,而我正在丢弃这些请求返回的令牌。 So, when Spring Security compared the tokens It used the authentication token which was invalid and not the token from the last request. 因此,当Spring Security比较令牌时,它使用了无效的身份验证令牌,而不是上次请求中的令牌。

Hope this help someone. 希望这能有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 错误HTTP状态403-在请求参数&#39;_csrf&#39;或标头&#39;X-CSRF-TOKEN&#39;上发现无效的CSRF令牌&#39;null&#39; - Error HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN' 春季启动-在请求参数&#39;_csrf&#39;或标头&#39;X-CSRF-TOKEN&#39;上发现无效的CSRF令牌&#39;null&#39; - Spring boot - Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN' HTTP状态403 - 在请求参数上找到无效的CSRF令牌“null” - HTTP Status 403 - Invalid CSRF Token 'null' was found on the request parameter spring如何使用_csrf参数或X-CSRF-TOKEN标头在内部验证csrf令牌? - How does the spring internally validate the csrf token with _csrf parameter or X-CSRF-TOKEN header? HTTP状态403-找不到预期的CSRF令牌 - HTTP Status 403 - Expected CSRF token not found 来自 Postman 的 Post 请求中的状态 403 无效的 CSRF 令牌 - Status 403 Invalid CSRF token in Post request from Postman X-CSRF-TOKEN 不是由 Spring Boot 生成的 - X-CSRF-TOKEN is not generated by Spring Boot 如何在 java REST 客户端中获取有效的 X-CSRF-TOKEN? - how to get valid X-CSRF-TOKEN in java REST Client? HTTP状态403 - 未找到预期的CSRF令牌。 你的会话已经过期了吗? - HTTP Status 403 - Expected CSRF token not found. Has your session expired? 使用 x-csrf-token 身份验证连接到 rest Web 服务时出错 - Error connecting to rest webservice with x-csrf-token authentication
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM