![](/img/trans.png)
[英]Restassured CSRF protection with X-XSRF-TOKEN (like angularjs) header
[英]CSRF/XSRF protection for Spring Security and AngularJS
我试图将CSRF / XSRF保护添加到我的应用程序中,但是遇到了奇怪的行为。 所有的get请求都可以正常工作,但是在所有发布/发布/删除操作中,我都得到403未经授权。 最奇怪的是,当我尝试调试CSRF过滤器时,请求没有到达,它们会在更早的某个地方被拒绝。 它们甚至没有到达我的身份验证筛选器,因此我无法弄清楚可能是什么问题。
我的安全配置:
@Override
public void configure(HttpSecurity http) throws Exception {
http
...
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService()), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.csrf().csrfTokenRepository(csrfTokenRepository());
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
我没有添加过滤器,因为正如我所说,请求没有到达它们。 但是,如果需要,我将完成我的问题。 希望对您有所帮助,在此先感谢您!
原则上,Spring中的CSRF机制将CSRF令牌存储在仅HTTP cookie中。 因为JavaScript无法访问仅HTTP的cookie,所以您需要告诉spring仅禁用HTTP:
.and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
然后,您可以从Angular中读取cookie,并将其与每个请求一起添加到XSRF-TOKEN标头中。
这是一般情况。 我不确定这是否适合您的特殊情况。
非常感谢您的回答,它们确实帮助我找到了解决方案。 如果将来有人遇到同样的问题,我想分享我的解决方案。
如答案中所述,我使用SessionCreationPolicy.STATELESS
且没有会话,因此我不得不使用CookieCsrfTokenRepository
和withHttpOnlyFalse()
来代替HttpSessionCsrfTokenRepository
,以允许AngularJS读取cookie。
结果,我有这样的配置:
@Override
public void configure(HttpSecurity http) throws Exception {
http
...
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService()), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
.csrf().csrfTokenRepository(csrfTokenRepository());
}
如果有人对CsrfHeaderFilter的外观感兴趣:
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);
}
}
我的第二个问题是CORS。 AngularJS文档说:
“不会为跨域请求设置标题。”
要解决此问题,我必须使用HTTP拦截器:
.factory('XsrfInterceptor', function ($cookies) {
return {
request: function (config) {
var headerName = 'X-XSRF-TOKEN';
var cookieName = 'XSRF-TOKEN';
config.headers[headerName] = $cookies.get(cookieName);
return config;
}
};
});
.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('XsrfInterceptor');
}]);
希望我的回答会有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.