Angular 4 can't set CSRF-TOKEN in header

匿名 (未验证) 提交于 2019-12-03 08:33:39

问题:

I've got a Spring boot RESTful service with Spring security configured like so:

protected void configure(HttpSecurity httpSecurity) throws Exception {         httpSecurity.cors().and()                 /*.formLogin().loginPage("/auth")                 .permitAll().and()                 .authorizeRequests()                 .anyRequest()                 .authenticated()                 .and().httpBasic().and()*/                 .csrf()                 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())                 .and()                 .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);     } 

&

public class CsrfHeaderFilter extends OncePerRequestFilter {  private static final String CSRF_COOKIE_NAME = "XSRF-TOKEN";  @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)         throws ServletException, IOException {      CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());     if (csrf != null) {         response.addHeader("X-CSRF-TOKEN", csrf.getToken());         Cookie cookie = WebUtils.getCookie(request, CSRF_COOKIE_NAME);         String token = csrf.getToken();          if (cookie == null || token != null && !token.equals(cookie.getValue())) {             cookie = new Cookie(CSRF_COOKIE_NAME, token);             cookie.setPath("/");             response.addCookie(cookie);         }     }      filterChain.doFilter(request, response); } 

}

I'm invoking the RESTful service using Angular 4 (latest version). It's doing a post request an complaining and throwing a 403 Forbidden "Could not verify the provided CSRF token because your session was not found." Which is expected because I when sending the post request the X-CSRF-TOKEN header is not being set but this header does exist:- Set-Cookie:XSRF-TOKEN=; Path=/

Angular:

auth.service.ts:

const body = 'SOMERANDOMKEY1111';  const headers = new HttpHeaders().set('Content-Type', 'application/json').set('withCredentials', 'true');      return this._http.post(this.endpoint + this.auth, body, {       headers: headers     }); 

app.module.ts (note: using HttpClient for post request):

providers: [ ... {     provide: XSRFStrategy, useFactory: xsrfFactory }...] export function xsrfFactory() {   return new CookieXSRFStrategy('XSRF-TOKEN', 'XSRF-TOKEN'); } 

I've followed this and read up on the docs but can't seem to get this working.

回答1:

The response is forbidden because the spring server or your proxy is expect to receive a X-CSRF token in the header and you did not send it.

1.Please make sure that you are doing a POST (on LOG IN) method to receive the CSRF-TOKEN

2.Store the token received in cookies or localstorage

3.Make the post and add token into the header like this:

let headers = new Headers({ 'XSRF-TOKEN', 'the token received after login' }); let options = new RequestOptions({ headers: headers }); return this.http.post(url,body,options); 


回答2:

If your Angular UI and RESTful service are in different domains, your Angular code can't read the cookie set by your backend. To resolve that in your local workspace you can set up cli proxy But for production, if you are using Apache HTTP server, you need to set up reverse proxy. Here is an example:

For https

<VirtualHost *:443>     ServerName localhost     SSLEngine on     SSLProxyEngine On     SSLCertificateFile conf/ssl/newfile.crt     SSLCertificateKeyFile conf/ssl/newfile.key     ProxyPass /api/ https://yoursite/api/     ProxyPassReverse /api/ https://yoursite/api/ </VirtualHost> 

For http

<VirtualHost *:80>     ServerName localhost     ProxyPass /api/ http://yoursite/api/     ProxyPassReverse /api/ http://yoursite/api/ </VirtualHost> 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!