Spring Security + AngularJS:POST 请求

Posted

技术标签:

【中文标题】Spring Security + AngularJS:POST 请求【英文标题】:Spring Security + AngularJS: POST request 【发布时间】:2015-10-04 11:35:15 【问题描述】:

我有一个 Web 应用程序,背面使用 Java Spring,正面使用 AngularJS。

Spring 安全配置(Java 配置)

@Override
protected void configure(HttpSecurity http) throws Exception 
        http
        .authenticationProvider(authenticationProvider())
        .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
        .and()
        .formLogin().loginProcessingUrl("loginProcessingUrl")
                    .successHandler(authSuccessHandler)
                    .failureHandler(authFailureHandler)
                    .usernameParameter("username")
                    .passwordParameter("password")
        .and()
        .logout().permitAll().logoutSuccessHandler(logoutSuccessHandler)
        .and()
        .authorizeRequests().antMatchers("/demo/**","/postTest/**").permitAll()
        .anyRequest().authenticated()
        .and()
        .httpBasic()
        .and()
        .csrf().csrfTokenRepository(csrfTokenRepository())
        .and()
        .addFilterAfter(new CsrfCustomFilter(), CsrfFilter.class);
    

CSRF 过滤器

public class CsrfCustomFilter 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);


来自 AngularJS 的 POST 请求

$http(method:'POST',data:"celine",url:"http://localhost:8080/postTest",cache:true)
        .success(function(data) 
          console.log("success POST");
        )
        .error(function(data, status, headers, config, statusText) 
          console.log("status: " + status + " statusText: " + statusText);
        );

-- 更新-- 我可以使用从前到后的 GET 请求,但 POST 请求似乎不起作用。我在前端收到 403 Forbidden 错误(在我的日志中:“status: 403 statusText: undefined”)。

对于 POST 请求,我可以正确地向 Spring 发送 XSRF-TOKEN,但 Spring 返回 403 Forbidden。所以我想问题出在我对 Spring Security 的配置上,而不是来自 Angular。

我的 POST 请求标头

感谢您的宝贵时间。

【问题讨论】:

阅读 $http 文档以了解 Angular 如何处理标头中的 xsrf 标记 感谢您的帮助。来自文档:“为了利用这个 [CSRF 保护],您的服务器需要在第一个 HTTP GET 请求上设置一个名为 XSRF-TOKEN 的 javascript 可读会话 cookie 中的令牌。”但是我想我的问题是因为我的 Spring 端没有发送 XSRF-TOKEN。 你不能只添加一个cookie吗? 我用 Java 实现了 CsrfCustomFilter 类来发送一个名为 XSRF-TOKEN 的 cookie。但它在我的 POST 请求标头中不可见。但是,它在 GET 响应的标头中可见。 你在使用跨域请求吗?我的意思是,您的客户端应用程序与服务器应用程序在不同的端口上运行吗? 【参考方案1】:

我在跨域请求中遇到了类似的问题,因为 AngularJS 不会在跨域请求中发送 XSRF 标头。 (在this page上搜索“不会为跨域请求设置标头”)。

写这个$http拦截器

angular.module('appBoot')
  .factory('XSRFInterceptor', function ($cookies, $log) 

    var XSRFInterceptor = 

      request: function(config) 

        var token = $cookies.get('XSRF-TOKEN');

        if (token) 
          config.headers['X-XSRF-TOKEN'] = token;
          $log.info("X-XSRF-TOKEN: " + token);
        

        return config;
      
    ;
    return XSRFInterceptor;
  );

并像这样配置它

angular.module('appBoot', ['ngCookies', 'ngMessages', 'ui.bootstrap', 'vcRecaptcha'])
    .config(['$httpProvider', function ($httpProvider) 

      $httpProvider.defaults.withCredentials = true;
      $httpProvider.interceptors.push('XSRFInterceptor');

    ]);

解决了我的问题。

【讨论】:

谢谢,我会试试看,如果成功了会通知你。 我已经更新了我的问题。现在我可以从 Angular 发送 XSRF-TOKEN,但我仍然从服务器端收到“403 Forbidden”。 希望您的 csrfTokenRepository() 将标头的名称设置为 X-XSRF-TOKEN。我在github.com/naturalprogrammer/spring-lemon 有一个工作示例。看看 LemonSecurityConfig.java 等文件有没有帮助。 是的,csrfTokenRepository() 将标头的名称设置为 X-XSRF-TOKEN。谢谢,我会试试你的github例子..

以上是关于Spring Security + AngularJS:POST 请求的主要内容,如果未能解决你的问题,请参考以下文章

Angular集成Spring Boot,Spring Security,JWT和CORS

Angular 2/Spring Security CSRF 实现问题

Angular 4.0 + Spring boot + Spring Security:TemplateInputException:解析模板“登录”时出错

如何使用 Spring Security + Angular 登录/验证

Angular 2 Spring Security CSRF 令牌

带有 Spring Boot 和 Spring Security 的 Angular2