AngularJS SpringBoot 没有认证 csrf 保护

Posted

技术标签:

【中文标题】AngularJS SpringBoot 没有认证 csrf 保护【英文标题】:AngularJS SpringBoot no authentication csrf protection 【发布时间】:2018-11-17 01:05:43 【问题描述】:

我的系统使用 AngularJS 1.6 和 Spring Boot2.0。我的前端只是一个简单的表单,客户可以使用它来购买活动门票。当页面加载时,它将获取当前活动事件的详细信息,然后用户可以填写要发布的表单。没有登录/注册,所以它就像一个谷歌表单。我将它们构建为单独的项目,因此它们将在不同的端口中运行。现在我想启用 csrf 保护,但我似乎无法让它工作。

我尝试按照本教程进行操作,但没有验证部分:https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii。当我这样做时,我在 GET 事件详细信息部分遇到了“CORS 标头‘Access-Control-Allow-Origin’缺失”,因此我添加了一个 CORS 过滤器:

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("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", "Content-Type");
chain.doFilter(request, response);

添加之后,我的 GET 可以工作,但是当我发布客户的详细信息时遇到相同的 CORS 错误。当我使用邮递员时,我已经可以在 cookie 中看到 XSRF-TOKEN,但不知何故我的后端阻止了传入的 POST。据我了解,Angular 自动使用接收到的 XSRF 令牌,因此在实现 Spring Security 时我没有在前端进行任何修改。

我也试过这个:https://sdqali.in/blog/2016/07/20/csrf-protection-with-spring-security-and-angular-js/。和完全相同的结果,如果我只是按照教程进行操作,GET 上出现 CORS 错误,那么当我添加简单的 CORS 过滤器时,POST 上出现 CORS 错误。我的过滤器似乎在运行时混淆了。

我尝试过使用这些教程中的代码以及堆栈中相关问题的一些答案,但它们都不必处理 CORS 问题。

【问题讨论】:

要在 spring-boot 上启用 CORS,您应该检查以下文档:docs.spring.io/spring/docs/current/spring-framework-reference/… 如果您也在使用 spring-security,请检查:docs.spring.io/spring-security/site/docs/current/reference/html/… 这些解决方案中的每一个都应该更干净一些您当前正在使用的那个。 【参考方案1】:

首先,您应该查看我对如何使用 spring-boot 和 spring-security 启用 CORS 的评论。

至于 CSRF 保护,带有 spring-security 的 spring-boot 2 直接启用。然而,要将它与 AngularJS 一起使用,您需要遵循本指南: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#csrf-cookie

我们也在开发一个前端 AngularJS 1.6 和后端 spring-boot 2 的项目,但是,由于我们没有将前端和后端部署在同一个 url 上,我们遇到了问题。

例子:

https://project.company.com/frontend https://project.company.com/backend

服务器生成的 cookie 设置在域 https://project.company.com 上,上下文为 /backend,这在 AngularJS 中的前端应用程序中无法读取。

为了解决这个问题,我们强制我们的服务器发送一个带有上下文 / 的 cookie,以便可以从两个应用程序中读取它。

@Configuration
@EnableWebSecurity
public class LdapAuthenticationSecurityConfiguration extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        final CookieCsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
        csrfTokenRepository.setCookiePath("/"); // Make sure that the cookie can be read from the backend and the frontend on the same domain.
        http.csrf().csrfTokenRepository(csrfTokenRepository);
        http.cors();
    

如果您的应用程序部署在不同的域上,但具有相同的基础,如下所示:

https://frontend.company.com https://backend.company.com

我建议强制服务器使用.company.com 之类的域发送cookie。但要这样做,您需要修改 spring-security 管理 cookie 创建的方式。

【讨论】:

以上是关于AngularJS SpringBoot 没有认证 csrf 保护的主要内容,如果未能解决你的问题,请参考以下文章

HttpBasic认证失败url

Django REST框架令牌认证AngularJS

angularjs+webapi2 跨域Basic 认证授权

SpringBoot整合Shiro 四:认证+授权

AngularJS ui-router 登录认证

springboot动态修改日志级别+权限认证