Spring Security 的 POST 响应标头中未设置 Angular 2 CSRF cookie

Posted

技术标签:

【中文标题】Spring Security 的 POST 响应标头中未设置 Angular 2 CSRF cookie【英文标题】:Angular 2 CSRF cookie not set in POST response header in Spring Security 【发布时间】:2017-08-21 16:22:01 【问题描述】:

我有一个适用于 Spring 的 Angular2 应用程序。后端(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 


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

当我尝试发布某些内容时会出现问题,但使用 GET 方法可以正常工作。我在我的 spring 配置中启用了 CSRF,我希望它保持这种状态。当我尝试发布时,我得到一个“403”代码。这是我用于配置 CSRF 的 CookieFilter 类。

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'.

【问题讨论】:

【参考方案1】:

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

Angular 的 http 在其 XSRFStrategy 中内置了对该技术的客户端部分的支持。默认的 CookieXSRFStrategy 会自动打开。在发送 HTTP 请求之前,CookieXSRFStrategy 会查找名为 XSRF-TOKEN 的 cookie,并使用该 cookie 的值设置名为 X-XSRF-TOKEN 的标头。

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

但正如您在下面的链接中看到的,您需要在 spring 中进行特殊配置,以允许 javascript(即 AngularJS)读取它。在文档中,他们命名为 AngularJS,但对于 Angular 2+ 来说是相同的。

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

【讨论】:

以上是关于Spring Security 的 POST 响应标头中未设置 Angular 2 CSRF cookie的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 会话 JSESSIONID

错误 405 请求方法 'POST' 不支持 Spring Security

Spring Security + AngularJS:POST 请求

405 - 请求方法“POST”不支持 Spring MVC + Spring Security

尽管有 SecurityConfig,但 Spring Security 会阻止 POST 请求

为啥在 Spring Security 的 hasPermission 检查中使用“#post”而不是“post”