苦苦挣扎了一段时间 . 我在后端使用带有Spring安全性(启用Cors-filter)的Java / J2EE(RESTFul)使用Angular.js . Spring尝试完全正常,除非我尝试启用csrf保护 . 下面是我为csrf尝试的代码:

我的CSRF过滤器

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

}

安全配置有以下代码:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
            .and()
            .formLogin()
                .successHandler(authSuccess)
                .failureHandler(authFailure)
            .and()
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .antMatchers("/admin/**").access("hasRole('ADMIN')")
                .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
            .and()
            .addFilterBefore(corsFilter, HeaderWriterFilter.class)
            .addFilterAfter(csrfHeaderFilter, CsrfFilter.class)
            .csrf().csrfTokenRepository(csrfTokenRepository());
            //.csrf().disable();
}

        private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setHeaderName("X-XSRF-TOKEN");
    return repository;
}

必须修改CORS过滤器以在Access-Control-Allow-Headers中添加X-XSRF-TOKEN标头名称,因为它最初提供此错误 .

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "X-XSRF-TOKEN, x-requested-with, Content-Type");
    chain.doFilter(req, res);
}

我的角度js代码:

$scope.login = function () {
            $http.post("http://localhost:9090/cynosureserver/login", "username=" + $scope.user.name +
                    "&password=" + $scope.user.password, {
                        headers: {
                            'Content-Type': 'application/x-www-form-urlencoded',
                            'X-XSRF-TOKEN': $cookies.get('XSRF-TOKEN')


                }
                    }).then(function (data) {
                alert("login successful" + JSON.stringify(data));
            }, function (err) {
                alert("error logging in" + JSON.stringify(err));
            });
        };

我有调试点设置 . 登录后,它将转到Csrf过滤器 . 但从来没有打过我的“CustomUserDetailsService” . 问题是我总是得到403回复说:

HTTP状态403 - 未找到预期的CSRF令牌 . 你的会话已经过期了吗?

如果我发出一个简单的Get请求它就会成功,并且在Response Header中也会收到“XSRF-TOKEN”cookie .

但对于我的帖子方法,我无法继续 . 我在下面看到:

Status Code:403 Forbidden
Remote Address:[::1]:9090

响应 Headers

Access-Control-Allow-Headers:X-XSRF-TOKEN, x-requested-with, Content-Type
Access-Control-Allow-Methods:POST, GET, PUT, OPTIONS, DELETE
Access-Control-Allow-Origin:*
.... 
Set-Cookie:JSESSIONID=5DE6DB8B5E31DC77DC4ED28600445615; Path=/cynosureserver/; HttpOnly
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block

请求 Headers

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
...
Content-Type:application/x-www-form-urlencoded
Host:localhost:9090
Origin:http://localhost:9000
Referer:http://localhost:9000/
X-XSRF-TOKEN:7c2057b5-0f1a-4dc1-bab4-c8f000a2ae2d

表格数据

username:manisha
password:123456

我尝试了很多不同的组合,但似乎没有任何效果,请帮帮我 - 我错过了什么?我在这里完全无能为力 . 对不起冗长的帖子 .