Angular 4 - setting withCredentials on every reque

2020-02-17 02:20发布

问题:

My angular client is separated from the backend and I have enabled cors on the backend, everything works fine except the fact that my authentication fails because the cookie is not added to requests.

After searching online I found that I should set {withCredentials : true} on every http request. I managed to do it on a single request and it works, but not on all the requests.

I tried using BrowserXhr How to send "Cookie" in request header for all the requests in Angular2? but it doesn't work and it's also deprecated afaik.

I also tried RequestOptions but it didn't work.

What can I do to set {withCredentials: true} on every http request?

Later Edit:

@Injectable()
export class ConfigInterceptor implements HttpInterceptor {

  constructor(private csrfService: CSRFService) {

  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let token = this.csrfService.getCSRF() as string;
    const credentialsReq = req.clone({withCredentials : true, setHeaders: { "X-XSRF-TOKEN": token } });
    return next.handle(credentialsReq);
  }
}

回答1:

You can use an HttpInterceptor.

@Injectable()
export class CustomInterceptor implements HttpInterceptor {

    constructor() {
    }

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

        request = request.clone({
            withCredentials: true
        });

        return next.handle(request);
    }
}

Next you have to provide it:

@NgModule({
  bootstrap: [AppComponent],
  imports: [...],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: CustomInterceptor ,
      multi: true
    }
  ]
})
export class AppModule {}

Source and full explanation



回答2:

Another perhaps more simple way is to create your own ApiService. It would use an injected HttpClient. All XHR requests would use the ApiService instead of HttpClient directly.

Here is an example implementation:

https://github.com/gothinkster/angular-realworld-example-app/blob/63f5cd879b5e1519abfb8307727c37ff7b890d92/src/app/core/services/api.service.ts

Some of the code that I have modified:

@Injectable()
export class ApiService {

  private httpOptions = {
    headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
    withCredentials: true // to allow cookies to go from "https://localhost:4567" to "http://localhost:5678"
  };

  constructor(
    private http: HttpClient
  ) { }

  private formatErrors(error: any) {
    return throwError(error.error);
  }

  get(path: string, params: HttpParams = new HttpParams()): Observable<any> {
    return this.http.get(`${environment.api_url}${path}`, { params })
      .pipe(catchError(this.formatErrors));
  }

  put(path: string, body: Object = {}): Observable<any> {
    return this.http.put(
      `${environment.api_url}${path}`,
      JSON.stringify(body),
      this.httpOptions
    ).pipe(catchError(this.formatErrors));
  }

  post(path: string, body: Object = {}): Observable<any> {
    return this.http.post(
      `${environment.api_url}${path}`,
      JSON.stringify(body),
      this.httpOptions
    ).pipe(catchError(this.formatErrors));
  }