繁体   English   中英

Spring CSRF保护仅用于登录

[英]Spring CSRF protection for login only

我将Spring用于Web应用程序的后端,并将使用Angular作为前端。 在尝试对本指南进行一些修改之后,我尝试将CS​​RF保护仅用于登录。 我想要实现的是,Angular首先将ajaxing修改为“ / init”,这将设置CSRF TOKEN cookie,然后它可以调用受CSRF保护的登录名。

当我调用/ init方法时,它会返回一个CSRF令牌,但是在此之后,当我调用/ login时,我会一直被禁止使用403。

这是请求(使用Postman进行测试):

POST /login HTTP/1.1
Host: localhost:8080
Accept: application/json
Content-Type: application/json
Cache-Control: no-cache

{"username":"test","password":"test"}

这是csrf的Java代码:

    private RequestMatcher csrfRequestMatcher = new RequestMatcher() {

    private RegexRequestMatcher requestMatcher =
            new RegexRequestMatcher("/login", null);

    @Override
    public boolean matches(HttpServletRequest request) {
        return requestMatcher.matches(request);
    }

};
    @Override
protected void configure(HttpSecurity http) throws Exception {

    http.csrf()
            .requireCsrfProtectionMatcher(csrfRequestMatcher)
            .and()
            .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
            .and().authorizeRequests().antMatchers("/test/**").authenticated()
            .and().addFilterAt(MyUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .formLogin().permitAll()
            .and().logout().logoutSuccessHandler(MyLogoutHandler())
            .and().addFilterAfter(new CsrfGrantingFilter(), SessionManagementFilter.class);
}




public class CsrfGrantingFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
    CsrfToken csrf = (CsrfToken) servletRequest.getAttribute(CsrfToken.class.getName());
    String token = csrf.getToken();
    if (token != null && isInit(servletRequest)) {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        Cookie cookie = new Cookie("XSRF-TOKEN", token);
        cookie.setPath("/");
        response.addCookie(cookie);
    }
    filterChain.doFilter(servletRequest, servletResponse);
}

private boolean isInit(ServletRequest servletRequest) {
    HttpServletRequest request = (HttpServletRequest) servletRequest;
    return request.getRequestURI().equals("/init");
}

@Override
public void destroy() {}
}

我是否缺少明显的东西? 还是我的要求不好?

Spring默认情况下启用CSRF,那么为什么必须要有requestMatcher,Filter等? 角已经内置支持CSRF - “XSRF”的基础上的cookies - https://angular.io/guide/http#security-xsrf-protection引述指南:“角希望cookie的名称是‘XSRF-TOKEN’而且Spring Security默认将其作为请求属性提供,因此我们只需要将值从请求属性转移到cookie。”

因此,要使其与Angular一起使用,请在confgiure()方法中将csrf()配置为

http.csrf()
     .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

只需调用/ login并成功登录,Angular(假设Angular 2+)就会从cookie中获取令牌并发送

一切都很好,但是我必须在标题中将令牌放在“ X-CSRF-TOKEN”键下,而不是XSRF-TOKEN或CSRF-TOKEN。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM