首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring CSRF仅用于登录保护

Spring CSRF仅用于登录保护
EN

Stack Overflow用户
提问于 2018-08-03 16:02:43
回答 2查看 1.1K关注 0票数 0

我正在使用Spring作为will应用程序的后端,并将使用Angular作为前端。我正在尝试使用CSRF的保护,只登录,在this guide与一些修改。我正在尝试实现的是,Angular首先将设置/init标记cookie的“CSRF”,然后它可以调用登录,这是CSRF保护。

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

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

代码语言:javascript
复制
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代码:

代码语言:javascript
复制
    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() {}
}

我是不是漏掉了什么明显的东西?或者仅仅是我的请求不好?

EN

回答 2

Stack Overflow用户

发布于 2018-08-03 16:59:09

CSRF在Spring中是默认启用的,那么为什么一定要有requestMatcher、Filter等?Angular内置了对基于cookie - https://angular.io/guide/http#security-xsrf-protection的CSRF - "XSRF“的支持,引用指南:"Angular希望cookie名称为"XSRF-TOKEN”,Spring Security默认将其作为请求属性提供,因此我们只需要将值从请求属性传输到cookie。“

因此,为了使其与Angular一起工作,在confgiure()方法中,将csrf()配置为

代码语言:javascript
复制
http.csrf()
     .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())

只需调用/login,成功登录后,Angular (假设Angular 2+)将从cookie中提取令牌并将其发送

票数 0
EN

Stack Overflow用户

发布于 2018-08-03 21:58:07

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51667946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档