如何使用 HttpClientXsrfModule angular 6 添加 x-xsrf-token

Posted

技术标签:

【中文标题】如何使用 HttpClientXsrfModule angular 6 添加 x-xsrf-token【英文标题】:How to add x-xsrf-token using HttpClientXsrfModule angular 6 【发布时间】:2019-07-30 09:17:57 【问题描述】:

我正在使用JWT 令牌进行身份验证并将其存储在本地存储中,现在想添加CSRF 令牌,是否可以仅以角度激活CSRF

作为 JWT 令牌生成,是否可以随机生成 CSRF 并存储它?

我正在尝试类似下面的东西

authentication.service.ts

    import  Injectable  from '@angular/core';
    import  HttpClient  from '@angular/common/http';
    import  Observable  from 'rxjs/Observable';
    import  map  from 'rxjs/operators/map';
    import  Router  from '@angular/router';

    export interface UserDetails 
    _id: string;
    email: string;
    name: string;
    exp: number;
    iat: number;
    

    interface TokenResponse 
  token: string;
   

   export interface TokenPayload 
  email: string;
  password: string;
  name?: string;


@Injectable()
export class AuthenticationService 
  private token: string;

  constructor(private http: HttpClient, private router: Router) 

  private saveToken(token: string): void 
    localStorage.setItem('mean-token', token);
    this.token = token;
  

  private getToken(): string 
    if (!this.token) 
      this.token = localStorage.getItem('mean-token');
    
    return this.token;
  

  public getUserDetails(): UserDetails 
    const token = this.getToken();
    let payload;
    if (token) 
      payload = token.split('.')[1];
      payload = window.atob(payload);
      return JSON.parse(payload);
     else 
      return null;
    
  

  public isLoggedIn(): boolean 
    const user = this.getUserDetails();
    if (user) 
      return user.exp > Date.now() / 1000;
     else 
      return false;
    
  

  private request(method: 'post'|'get', type: 'login'|'register'|'profile', user?: TokenPayload): Observable<any> 
    let base;

    if (method === 'post') 
      base = this.http.post(`/api/$type`, user);
     else 
      base = this.http.get(`/api/$type`,  headers:  Authorization: `Bearer $this.getToken()` );
    

    const request = base.pipe(
      map((data: TokenResponse) => 
        if (data.token) 
          this.saveToken(data.token);
        
        return data;
      )
    );

    return request;
  

  public register(user: TokenPayload): Observable<any> 
    return this.request('post', 'register', user);
  

  public login(user: TokenPayload): Observable<any> 
    return this.request('post', 'login', user);
  

  public profile(): Observable<any> 
    return this.request('get', 'profile');
  

  public logout(): void 
    this.token = '';
    window.localStorage.removeItem('mean-token');
    this.router.navigateByUrl('/');
  

auth.interceptor.ts

import  Injectable, Injector  from '@angular/core';
import  HttpInterceptor, HttpEvent, HttpRequest, HttpHandler, HttpXsrfTokenExtractor  from '@angular/common/http';
import  Observable  from 'rxjs/Observable';

@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor 

  constructor(private tokenExtractor: HttpXsrfTokenExtractor) 
  

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> 
    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

import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';
import  HttpClientModule, HttpClientXsrfModule, HTTP_INTERCEPTORS  from '@angular/common/http';
import  FormsModule  from '@angular/forms';
import  RouterModule, Routes  from '@angular/router';

import  AppComponent  from './app.component';
import  ProfileComponent  from './profile/profile.component';
import  LoginComponent  from './login/login.component';
import  RegisterComponent  from './register/register.component';
import  HomeComponent  from './home/home.component';
import  AuthenticationService  from './authentication.service';
import  AuthGuardService  from './auth-guard.service';
import  HttpXsrfInterceptor  from './auth.interceptor';

const routes: Routes = [
   path: '', component: HomeComponent ,
   path: 'login', component: LoginComponent ,
   path: 'register', component: RegisterComponent ,
   path: 'profile', component: ProfileComponent, canActivate: [AuthGuardService] 
];

@NgModule(
  declarations: [
    AppComponent,
    ProfileComponent,
    LoginComponent,
    RegisterComponent,
    HomeComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    HttpClientXsrfModule.withOptions(
      cookieName: 'My-Xsrf-Cookie', 
      headerName: 'My-Xsrf-Header' 
    ),
    RouterModule.forRoot(routes),
  ],
  providers: [
    provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true ,
    AuthenticationService, 
    AuthGuardService

  ],
  bootstrap: [AppComponent]
)
export class AppModule  

【问题讨论】:

【参考方案1】:

不要使用绝对路径,例如:

this.http.post<any>("https://example.com/api/endpoint",data)

使用

this.http.post<any>("api/endpoint",data)

或使用

this.http.post<any>("//example.com/api/endpoint",data)

这是因为绝对路径被 HttpClientXsrfModule 上的 Angular 代码显式忽略 (check it here)

【讨论】:

以上是关于如何使用 HttpClientXsrfModule angular 6 添加 x-xsrf-token的主要内容,如果未能解决你的问题,请参考以下文章

[精选] Mysql分表与分库如何拆分,如何设计,如何使用

如果加入条件,我该如何解决。如果使用字符串连接,我如何使用

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等