[英]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("/");
});
}
});
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: 资源链接:
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);
}
For those who are facing the same problem. 对于那些面临同样问题的人。 Here is my solution. 这是我的解决方案。
Hope this help someone. 希望这能有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.