我在将auth.service.ts
中的POST响应中的令牌传递到HttpInterceptor并将其设置在授权标头中时遇到问题。
据我了解,拦截器会在任何HTTP请求之前运行,拦截,修改并返回克隆的版本。
但是我的标题没有更新。在运行auth.service和发出BehaviorSubject的新值之前,拦截器仅返回tokenSubject$
的默认值null
。
浏览器控制台
interceptor null
auth.service.ts:19 {token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
auth.service.ts:21 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
原始标题
Host: localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:4200/login
Authorization: Bearer null
Content-Type: application/json
Content-Length: 52
Origin: http://localhost:4200
DNT: 1
Connection: keep-alive
我应该如何在授权标头中添加令牌?
auth.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService {
tokenSubject$ = new BehaviorSubject(null);
constructor(private httpClient: HttpClient) {}
login(userEmailAndPassword: { email: string, password: string }) {
return this.httpClient
.post<{ token: string }>('http://localhost:3000/users/login', userEmailAndPassword)
.subscribe(user => {
console.log(user); // { token: "eyJhbGciOiJIUzI..." }
this.tokenSubject$.next(user.token);
console.log(this.tokenSubject$.value); // "eyJhbGciOiJIUzI..."
});
}
}
jwt-interceptor.ts
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import { AuthService } from './auth.service';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const setAuthorizationToken = req.clone({
headers: req.headers.set('Authorization', `Bearer ${this.authService.tokenSubject$.value}`)
});
console.log('interceptor', this.authService.tokenSubject$.value);
return next.handle(setAuthorizationToken);
}
}
app.module.ts
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { LoginComponent } from './login/login.component';
import { JwtInterceptor } from './jwt-interceptor';
import { RouterModule, Routes } from '@angular/router';
import { UsersComponent } from './users/users.component';
const routes: Routes = [
{path: 'login', component: LoginComponent},
{path: 'signup', component: SignupComponent},
{path: 'users', component: UsersComponent}
];
@NgModule({
declarations: [
AppComponent,
SignupComponent,
LoginComponent,
UsersComponent
],
imports: [
RouterModule.forRoot(routes),
BrowserModule,
HttpClientModule,
ReactiveFormsModule
],
providers: [{provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true}],
bootstrap: [AppComponent]
})
export class AppModule {}
HTTP请求
POST http://localhost:3000/users/login
Content-Type: application/json
{
"email": "mr@mr.com",
"password": "myawesomepassword"
}
HTTP响应
POST http://localhost:3000/users/login
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8
Content-Length: 209
ETag: W/"d1-MJNo/MXLpxhkX1PE78vlqkKR5GQ"
Date: Wed, 28 Aug 2019 09:07:42 GMT
Connection: keep-alive
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response code: 200 (OK); Time: 15ms; Content length: 209 bytes
答案 0 :(得分:1)
您应该将auth令牌保存在服务之外的其他位置,因为每次重新加载页面时它将为null。我建议使用localstorage:
login(userEmailAndPassword: { email: string, password: string }) {
return this.httpClient
.post<{ token: string }>('http://localhost:3000/users/login', userEmailAndPassword)
.subscribe(user => {
console.log(user); // { token: "eyJhbGciOiJIUzI..." }
this.tokenSubject$.next(user.token);
localStorage.setItem('token', user.token);// --> Here u are saving the token to localstorage
console.log(this.tokenSubject$.value); // "eyJhbGciOiJIUzI..."
});
}
您还可以保存整个用户对象:
login(userEmailAndPassword: { email: string, password: string }) {
return this.httpClient
.post<{ token: string }>('http://localhost:3000/users/login', userEmailAndPassword)
.subscribe(user => {
console.log(user); // { token: "eyJhbGciOiJIUzI..." }
this.tokenSubject$.next(user.token);
localStorage.setItem('user', JSON.stringify(user));// --> Here u are saving the user to localstorage
console.log(this.tokenSubject$.value); // "eyJhbGciOiJIUzI..."
});
}
要从localstorage中检索用户,您必须将其解析为JSON:
JSON.parse(localStorage.getItem("user"));
然后在您的拦截器中执行以下操作:
const setAuthorizationToken = request.clone({
headers: new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'Bearer ' + localStorage.getItem('token') === null ? '' : localStorage.getItem('token');
})
});
通常,我编写一个UserService来从本地存储中检索令牌/用户。
致谢