Spring Security Угловой токен Csrf - PullRequest
0 голосов
/ 16 марта 2019

Я настроил Spring Security, но все еще не могу отправить почтовый запрос через Angular:

  @Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .authenticationProvider(credentialsAuthenticationProvider)
            .httpBasic()
            .and()
            .logout()
            .and()
            .cors().configurationSource(corsConfigurationSource)
            .and()
            .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}

/* To allow Pre-flight [OPTIONS] request from browser */
@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}

Мой источник конфигурации Cors выглядит следующим образом:

    public CorsConfigurationSource corsConfigurationSource() {
    final CorsConfiguration configuration = new CorsConfiguration();
    List<String> allowedOrigins = new LinkedList<>();
    allowedOrigins.add("*");
    List<String> allowedHeaders = new LinkedList<>();
    allowedHeaders.add("*");
    List<String> allowedMethods = new LinkedList<>();
    allowedMethods.add("HEAD");
    allowedMethods.add("GET");
    allowedMethods.add("POST");
    allowedMethods.add("PUT");
    allowedMethods.add("DELETE");
    allowedMethods.add("PATCH");
    allowedMethods.add("OPTIONS");
    configuration.setAllowedOrigins(allowedOrigins);
    configuration.setAllowedMethods(allowedMethods);
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(allowedHeaders);
    allowedHeaders.add("Authorization");
    allowedHeaders.add("Content-Type");
    allowedHeaders.add("x-xsrf-token");
    allowedHeaders.add("xsrf-token");
    allowedHeaders.add("Accept-language");
    allowedHeaders.add("X-Requested-With");
    configuration.setAllowedHeaders(allowedHeaders);
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

, и я использую rootконтекст: api / v1 в случае, если это может помочь.

на угловой стороне я настроил app.module.ts

  imports: [
...
HttpClientModule,
HttpClientXsrfModule,

],

проблема возникает, когда я пытаюсьпочтовый запрос: вот скриншот запроса и ответа:

GET Запрос возвращает 200 OK:

Получить запрос

Почтовый запрос возвращает 403 запрещенных:

Странно то, что есть 2 токена XSRF, которые, как я предполагаю, являются источником проблемы.

почтовый запрос

1 Ответ

0 голосов
/ 21 июня 2019

Чтобы решить проблему csrf между безопасностью пружины и угловым режимом, необходимо сделать это.

заменить .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()); на

        csrf()
        .ignoringAntMatchers ("/login","/logout")
        .csrfTokenRepository (this.getCsrfTokenRepository());

}
private CsrfTokenRepository getCsrfTokenRepository() {
        CookieCsrfTokenRepository tokenRepository = 
        CookieCsrfTokenRepository.withHttpOnlyFalse();
        tokenRepository.setCookiePath("/");
        return tokenRepository;
}

Угловой перехватчик csrf по умолчанию не всегда работает.Таким образом, вы должны реализовать свой собственный перехватчик.

import {Injectable, Inject} from '@angular/core';
import {HttpInterceptor, HttpXsrfTokenExtractor, HttpRequest, HttpHandler,
  HttpEvent} from '@angular/common/http';
import {Observable} from "rxjs";


@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {

  constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    let requestMethod: string = req.method;
    requestMethod = requestMethod.toLowerCase();

    if (requestMethod && (requestMethod === 'post' || requestMethod === 'delete' || requestMethod === 'put')) {
      const headerName = 'X-XSRF-TOKEN';
      let token = this.tokenExtractor.getToken() as string;
      if (token !== null && !req.headers.has(headerName)) {
        req = req.clone({headers: req.headers.set(headerName, token)});
      }
    }

    return next.handle(req);
  }
}

И, наконец, добавить его в свои провайдеры (app.module.ts)

providers: [{ provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true }]

Подумайте о том, чтобы включить импорт.

HttpClientXsrfModule.withOptions({
      cookieName: 'XSRF-TOKEN',
      headerName: 'X-CSRF-TOKEN'
}),
...