为什么在Spring Boot + Angular 7中出现403错误“缺少CSRF令牌”?

时间:2019-04-30 14:06:24

标签: spring-boot angular7 csrf-token

我正在Spring Boot + Angular 7应用程序中实现csrf,我担心的是当我进行登录时,我可以毫无问题地登录到该应用程序中。但是登录后csrf cookie没有更改,因此我从服务器收到403(CSRF已过期)错误,

但是当我刷新时它将正常工作。主要原因是cookie无法正确获取,我不知道问题出在哪里,例如来自客户端或服务器端。请帮助

我正在分享我的代码

Spring引导代码

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().and().csrf() // csrf config starts here
        .csrfTokenRepository(csrfTokenRepository())
        .ignoringAntMatchers("/", "/login", "/captcha-servlet", "/validateOTP", "supportApp/logout")
        .and()
        .addFilterAfter(new CustomCsrfFilter(), CsrfFilter.class);
}


private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setHeaderName("X-XSRF-TOKEN");
    return repository;
}

CSRF过滤器

public class CustomCsrfFilter 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();
            cookie = new Cookie("XSRF-TOKEN", token);
            cookie.setPath("/");
            response.addCookie(cookie);
        }
        filterChain.doFilter(request, response);
    }
}

CSRF角代码

import { HttpClient, HttpXsrfTokenExtractor, HttpHeaders } from '@angular/common/http';

constructor(private http: HttpClient, private tokenExtractor: HttpXsrfTokenExtractor) { }

const _csrf_token = this.tokenExtractor.getToken() as string;
return this.http.post(this._singleuserUrl, uid, {headers: new HttpHeaders().set('X-XSRF-TOKEN', _csrf_token), withCredentials: true});

1 个答案:

答案 0 :(得分:1)

您似乎忘记了将 HttpClientXsrfModule 导入app.module.ts

在Angular 6中为我工作。

app.module.ts

    imports: [
    HttpClientXsrfModule.withOptions({
      cookieName: "XSRF-TOKEN",
      headerName: "X-XSRF-TOKEN"
      }),
    ...
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: HttpXSRFInterceptor, multi: true },
    ...
  ],

此外,我使用拦截器将令牌设置为HEADER

HttpXSRFInterceptor

@Injectable()
export class HttpXSRFInterceptor implements HttpInterceptor {

  constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const headerName = 'XSRF-TOKEN';
    const respHeaderName = 'X-XSRF-TOKEN';
    let token = this.tokenExtractor.getToken() as string;
    if (token !== null && !req.headers.has(headerName)) {
      req = req.clone({ headers: req.headers.set(respHeaderName, token) });
    }
    return next.handle(req);
  }
}

此外,您可以使用邮递员说明服务器中的配置是否正常。

希望它会有所帮助。