2

我在 Spring Boot+Angular 7 应用程序中实现 csrf,我担心的是当我登录时,我可以毫无问题地登录应用程序。但是在登录 csrf cookie 后没有改变,所以我从服务器收到 403 (CSRF is expired) 错误,

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

我正在分享我的代码

春季启动代码

@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});

4

1 回答 1

2

看起来您忘记将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

HttpXSRF拦截器

@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);
  }
}

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

希望它可以帮助。

于 2019-11-26T11:08:09.713 回答