AngularJS SpringBoot无认证csrf保护

时间:2018-06-07 07:53:10

标签: angularjs spring-boot cors csrf-protection

我的系统使用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问题。

1 个答案:

答案 0 :(得分:0)

开始之前,您应该检查一下我如何使用spring-boot和spring-security启用CORS的评论。

对于CSRF保护,具有弹簧安全性的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创建的方式。