Angular 2 CSRF cookie 未在 POST 响应 header 中设置 Spring 安全

Angular 2 CSRF cookie not set in POST response header in Spring Security

我有一个 Angular2 应用程序可以与 Spring 一起使用。后端 (spring) 在另一个端口上运行,所以我按如下方式配置了 CORS。

    public GlobalCorsfilter() {
super();
}

@Override
public final void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");

// without this header jquery.ajax calls returns 401 even after successful login and SSESSIONID being succesfully stored.
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Origin, Content-Type, Version");
response.setHeader("Access-Control-Expose-Headers", "X-Requested-With, Authorization, Origin, Content-Type");

final HttpServletRequest request = (HttpServletRequest) req;
if (request.getMethod() != "OPTIONS") {
    chain.doFilter(req, res);
} else {
    //
}
}

@Override
public void destroy() {

}

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}

我猜这段代码工作正常,因为我没有收到任何错误。

当我尝试 POST 某些东西时出现问题,但它可以正常使用 GET 方法。我在 spring 配置中启用了 CSRF,我希望它保持这种状态。当我尝试 POST 时收到“403”代码。这是我的 CookieFilter class 用于配置 CSRF。

public class CsrfCookieGeneratorFilter extends OncePerRequestFilter {

@Override
protected void doFilterInternal(HttpServletRequest request,      HttpServletResponse response, FilterChain filterChain) throws  ServletException, IOException {
// Spring put the CSRF token in session attribute "_csrf"
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");

// Send the cookie only if the token has changed
String actualToken = request.getHeader("X-CSRF-TOKEN");
if (actualToken == null || !actualToken.equals(csrfToken.getToken())) {
    // Session cookie that will be used by AngularJS
    CookieGenerator cookieGenerator = new CookieGenerator();
    cookieGenerator.setCookieName("CSRF-TOKEN");
    cookieGenerator.setCookieHttpOnly(false);
    cookieGenerator.setCookieMaxAge(-1);
    cookieGenerator.setCookiePath("/");
    cookieGenerator.addCookie(response, csrfToken.getToken());
}

filterChain.doFilter(request, response);
}

这是我的 Spring 配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .addFilterBefore(new GlobalCorsfilter(), ChannelProcessingFilter.class)
        .addFilterAfter(new CsrfCookieGeneratorFilter(), CsrfFilter.class)
        .exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint)
        .and()
        .........

我已经在 Angular 2:

中添加了这行代码
{provide: XSRFStrategy, useValue: new CookieXSRFStrategy('CSRF-TOKEN', 'X-CSRF-TOKEN')}

我在响应中收到此消息:

Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

根据 Angular2 文档,如果您使用 http 方法,它默认会处理 CSRF,因此您不需要添加任何提供程序,除非您想要自定义 XSRF 策略。

Angular's http has built-in support for the client-side half of this technique in its XSRFStrategy. The default CookieXSRFStrategy is turned on automatically. Before sending an HTTP request, the CookieXSRFStrategy looks for a cookie called XSRF-TOKEN and sets a header named X-XSRF-TOKEN with the value of that cookie.

https://angular.io/docs/ts/latest/guide/security.html#!#http

但是正如您在下面的 link 中看到的那样,您需要在 spring 中进行特殊配置才能允许 JavaScript(即 AngularJS)阅读它。在文档中他们将 AngularJS 命名为 Angular 2+.

http://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html#csrf-cookie