将 AngularJS 与 SpringSecurity3.2 一起用于 CSRF

Posted

技术标签:

【中文标题】将 AngularJS 与 SpringSecurity3.2 一起用于 CSRF【英文标题】:Using AngularJS with SpringSecurity3.2 for CSRF 【发布时间】:2014-07-24 05:59:00 【问题描述】:

AngularJS

index.html

<head>
    <meta name="_csrf" content="$_csrf.token"/>
    <!-- default header name is X-CSRF-TOKEN -->
    <meta name="_csrf_header" content="$_csrf.headerName"/>
</head>

SpringSecurity 3.2

Spring 使用 HttpSessionCsrfTokenRepository,默认情况下 CSRF 的标头名称为 X-CSRF-TOKEN,但 Anuglar 约定是 X-XSRF-TOKEN

我想扩展 HttpSessionCsrfTokenRepository 并覆盖标头名称,但由于它被标记为 final 我最终实现了自定义令牌存储库。

@Component
public class CustomCsrfTokenRepository implements CsrfTokenRepository 

  public static final String CSRF_PARAMETER_NAME = "_csrf";

  public static final String CSRF_HEADER_NAME = "X-XSRF-TOKEN";

  private final Map<String, CsrfToken> tokenRepository = new ConcurrentHashMap<>();

  public CustomCsrfTokenRepository() 
    log.info("Creating ", CustomCsrfTokenRepository.class.getSimpleName());
  

  @Override
  public CsrfToken generateToken(HttpServletRequest request) 
    return new DefaultCsrfToken(CSRF_HEADER_NAME, CSRF_PARAMETER_NAME, createNewToken());
  

  @Override
  public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) 
    String key = getKey(request);
    if (key == null)
      return;

    if (token == null) 
      tokenRepository.remove(key);
     else 
      tokenRepository.put(key, token);
    
  

  @Override
  public CsrfToken loadToken(HttpServletRequest request) 
    String key = getKey(request);
    return key == null ? null : tokenRepository.get(key);
  

  private String getKey(HttpServletRequest request) 
    return request.getHeader("Authorization");
  

  private String createNewToken() 
    return UUID.randomUUID().toString();
  

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    @Inject
    private CustomCsrfTokenRepository customCsrfTokenRepository;


     @Override
        protected void configure(HttpSecurity http) throws Exception 

            http
    //          .addFilterAfter(new CsrfTokenGeneratorFilter(), CsrfFilter.class)
                .exceptionHandling()
                    .authenticationEntryPoint(authenticationEntryPoint)
                    .and()
                .formLogin()
                    .loginProcessingUrl("/app/authentication")
                    .successHandler(ajaxAuthenticationSuccessHandler)
                    .failureHandler(ajaxAuthenticationFailureHandler)
                    .usernameParameter("j_username")
                    .passwordParameter("j_password")
                    .permitAll()
                    .and()

                 .csrf()
                    .csrfTokenRepository(customCsrfTokenRepository)
                    .and()
              
           

    如何干净地覆盖标头名称而不是创建自定义 csrfTokenRepository?

    我是否需要对单页进行任何其他配置更改 AngularJS 等应用程序,因为它还不能工作。

【问题讨论】:

【参考方案1】:

当为 Spring Security 使用 Java 配置时,以下应该是可能的:

  public void configure(final HttpSecurity http) throws Exception
  
    final HttpSessionCsrfTokenRepository tokenRepository = new HttpSessionCsrfTokenRepository();
    tokenRepository.setHeaderName("X-XSRF-TOKEN");

    http.csrf().csrfTokenRepository(tokenRepository);
  

复杂之处在于单页应用程序依赖于 AJAX,并且在 AJAX 请求中包含 CSRF 令牌有点复杂。使用 AngularJS 时,服务器应在第一次请求以及用户登录或注销时发送一个名为 XSRF-TOKEN 的会话 cookie。然后,AngularJS 将在 HTTP 标头 X-XSRF-TOKEN 中返回此 cookie 的值以及所有请求,然后服务器可以对其进行检查。

【讨论】:

我看到人们使用过滤器在响应标头中发送 cookie。示例github.com/aditzel/spring-security-csrf-filter/blob/master/src/… 和 spring 文档“有人可能会问为什么预期的 CsrfToken 没有存储在 cookie 中。这是因为存在已知的漏洞,其中标头(即指定 cookie)可以由另一个域设置”。您是否有一个示例表明 spring 在“会话 Cookie”中发送回 CSRF 令牌? 正如您所提到的,Spring Security 不提供对在 cookie 中设置 CSRF 令牌的开箱即用支持。编写过滤器是最好的方法。 请检查此线程***.com/questions/31293303/…中的组合答案@

以上是关于将 AngularJS 与 SpringSecurity3.2 一起用于 CSRF的主要内容,如果未能解决你的问题,请参考以下文章

将 AngularJS 与 SharePoint WebParts 一起使用时推荐的方法是啥

如何将 Apache Shiro 与 AngularJS 集成

如何将 Flot 与 AngularJS 集成?

将 HTTP/2 与 angularJS 一起使用

Angularjs + Typescript,如何将 $routeParams 与 IRouteParamsService 一起使用

我们应该将 jQuery 与 AngularJS 一起使用吗? [关闭]