我正在开发一个Web应用程序,它有一个带有angularjs的前端和一个带有弹簧安全和平针织物的后端。
我正在尝试实现spring-security。我可以验证用户身份。但我坚持退出点。我正在将X-CSRF-TOKEN发送到一个值中,但似乎spring-security拒绝它。
的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>
弹簧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)
$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
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("/");
});
}
});
答案 0 :(得分:2)
XSRF是一种未经授权的网站可以获取用户身份的技术 私人数据。 Angular提供了一种对抗XSRF的机制。什么时候 执行XHR请求时,$ http服务从cookie中读取令牌 (默认情况下为XSRF-TOKEN)并将其设置为HTTP标头(X-XSRF-TOKEN)。
如果您设置了合适的Cookie,那么它会确保 angular会在内部处理标题
因此,在这种情况下,您需要检查每个请求服务器配置都不需要新令牌
您需要在提交表单时发送csrf
令牌。您需要在HTML表单中添加以下行:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
资源链接:
由于CodeMed建议添加
.antMatchers("/send-pin").permitAll()
在SecurityConfiguration
课程中。他有一些问题如下所述:
检查Firefox调试工具的“网络”选项卡,显示 以下两个cookie随请求一起发送: JSESSIONID:“99192501E7CEA0EDEF853BD666AF3C35”和 XSRF-TOKEN:“b50afb87-e15c-4bef-93ca-7c2fdf145fd8”,即使 同一请求的服务器日志仍然归结为无效的CSRF 找到http://localhost:9000/send-pin的令牌。这引起了我的注意 检查发送令牌被拒绝的原因,以及几分钟后 我注意到url模式缺少的antmatchers(...),导致 这个答案。
此更改导致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);
}
答案 1 :(得分:0)
对于那些面临同样问题的人。这是我的解决方案。
希望这有助于某人。