我是'm using Spring for a webapplication'的后端,并将使用Angular作为前端 . 我正在尝试使用CSRF保护仅用于登录,在this guide之后进行了一些修改 . 我想要实现的是,Angular首先ajaxing到"/init"将设置CSRF TOKEN cookie,然后它可以调用登录,这是CSRF保护的 .
当我调用/ init方法时,它会返回一个CSRF令牌,但是在我调用/登录之后,我一直禁止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() {}
}
我错过了一些明显的东西吗或者只是我的要求不好?
2 回答
在Spring中默认启用CSRF,那么为什么必须有requestMatcher,Filter等? Angular内置支持CSRF - "XSRF"基于cookie - https://angular.io/guide/http#security-xsrf-protection引用指南:"Angular wants the cookie name to be " XSRF-TOKEN " and Spring Security provides it as a request attribute by default, so we just need to transfer the value from a request attribute to a cookie."
因此,为了使它与Angular一起使用,在confgiure()方法中,将csrf()配置为
只需调用/登录,成功登录后,Angular(假设Angular 2)将从cookie中获取令牌并发送
一切都很好,但在 Headers 中我必须将令牌放在“X-CSRF-TOKEN”键下,而不是XSRF-TOKEN或CSRF-TOKEN .