Angular 401错误代码上未刷新刷新令牌
每个教程和代码段都在使用这种刷新令牌代码:在我的例子中,这根本不起作用,因为Angular 401错误代码上未刷新刷新令牌,angular,asp.net-core,Angular,Asp.net Core,每个教程和代码段都在使用这种刷新令牌代码:在我的例子中,这根本不起作用,因为this.authService.refreshttoken()执行HTTP post请求,直到发出订阅()后才会执行调用。当我添加subscribe调用时,它会在一个新请求中调用httppost,但这在我的脑海中是一团糟的。你能解释一下并告诉我如何正确处理这个问题吗?请不要将我已经看到的片段链接到我 有关我的ASP.NET Core 2.2 Web API后端的信息: /api/auth/login返回AccessT
this.authService.refreshttoken()
执行HTTP post请求,直到发出订阅()
后才会执行调用。当我添加subscribe调用时,它会在一个新请求中调用httppost,但这在我的脑海中是一团糟的。你能解释一下并告诉我如何正确处理这个问题吗?请不要将我已经看到的片段链接到我
有关我的ASP.NET Core 2.2 Web API后端的信息:
- /api/auth/login返回AccessToken(JWT令牌+刷新令牌字符串)。JWT令牌将在1分钟内过期,仅用于测试目的。刷新令牌将在10分钟后过期
- /api/auth/token/refresh返回一个新的AccessTokenJWT和Refresh令牌都将重新创建。另一件重要的事情是如果Refresh令牌过期,并且在此之后发出了刷新请求,则返回一个BADDREQUEST,该请求应该在角度部分进行处理,可能在管道内部有一个
catchError()
- /api/auth/logout将撤销刷新令牌。因此,基本上,在
上也会有http post请求,即使它不在我下面给出的代码中this.authService.logout()
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpErrorResponse
} from '@angular/common/http';
import { Observable, throwError, BehaviorSubject } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import { AuthService } from '../services/auth.service';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private refreshTokenInProgress = false;
private tokenSubject = new BehaviorSubject<any>(null);
constructor(private authService: AuthService) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.pipe(
catchError((error: HttpErrorResponse) => {
if (error instanceof HttpErrorResponse) {
if (error.status === 401) {
return this.handleHttpResponseError(request, next);
}
}
return throwError(error);
})
);
}
private handleHttpResponseError(request: HttpRequest<any>, next: HttpHandler) {
const accessToken = this.authService.getJwtToken();
// if jwt token is not set, we just let the request execute
if (!accessToken) {
return next.handle(request);
}
// if jwt token has not expired yet, we add the authorize header
// otherwise we refresh the token
if (!this.authService.isTokenExpired()) {
console.log('added authorization to the headers')
return next.handle(this.attachTokenToRequest(request, accessToken));
} else {
console.log('token expired');
this.authService.refreshToken()
.pipe(
switchMap(result => {
console.log(`API returned: ${result}`);
return next.handle(this.attachTokenToRequest(request, accessToken));
})
);
return next.handle(request);
}
}
private attachTokenToRequest(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
}
}
从'@angular/core'导入{Injectable};
进口{
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpErrorResponse
}来自“@angular/common/http”;
从“rxjs”导入{observatable,throwError,BehaviorSubject};
从“rxjs/operators”导入{catchError,switchMap};
从“../services/auth.service”导入{AuthService};
@可注射()
导出类AuthInterceptor实现HttpInterceptor{
私有refreshTokenInProgress=false;
私有令牌主体=新行为主体(null);
构造函数(私有authService:authService){}
拦截(请求:HttpRequest,下一步:HttpHandler):可观察{
返回next.handle(请求)
.烟斗(
catchError((错误:HttpErrorResponse)=>{
if(HttpErrorResponse的错误实例){
如果(error.status==401){
返回此.handleHttpResponseError(请求,下一步);
}
}
返回投掷器(错误);
})
);
}
私有handleHttpResponseError(请求:HttpRequest,下一步:HttpHandler){
const accessToken=this.authService.getJwtToken();
//如果没有设置jwt令牌,我们就让请求执行
如果(!accessToken){
下一步返回。处理(请求);
}
//如果jwt令牌尚未过期,则添加authorize标头
//否则我们刷新令牌
如果(!this.authService.isTokenExpired()){
console.log('向标头添加了授权')
返回next.handle(this.attachtokentoquest(request,accessToken));
}否则{
console.log('tokenexpired');
this.authService.refreshToken()
.烟斗(
开关映射(结果=>{
log(`API返回:${result}`);
返回next.handle(this.attachtokentoquest(request,accessToken));
})
);
下一步返回。处理(请求);
}
}
私有attachTokenToRequest(请求:HttpRequest,令牌:string){
return request.clone({
集合标题:{
授权:`Bearer${token}`
}
});
}
}
auth.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'src/environments/environment';
import { map } from 'rxjs/operators';
import { JwtHelperService } from '@auth0/angular-jwt';
import { AccessToken } from '../types/user';
@Injectable()
export class AuthService {
private actionUrl: string;
private readonly JWT_TOKEN = 'access_token';
private readonly REFRESH_TOKEN = 'refresh_token';
constructor(private httpClient: HttpClient) {
this.actionUrl = `${environment.baseUrls.server}api/auth`;
}
isLoggedIn(): boolean {
return !!this.getJwtToken();
}
login(credentials: { email: string, password: string }) {
return this.httpClient.post<AccessToken>(`${this.actionUrl}/login`, credentials)
.pipe(
map(tokens => {
this.setJwtToken(tokens.accessToken);
this.setRefreshToken(tokens.refreshToken);
return true;
})
);
}
refreshToken() {
console.log('refreshToken() called');
const helper = new JwtHelperService();
const email = helper.decodeToken(this.getJwtToken()).sub;
return this.httpClient.post<AccessToken>(`${this.actionUrl}/token/refresh`, { 'refreshToken': localStorage.getItem(this.REFRESH_TOKEN), 'email': email })
.pipe(
map(tokens => {
console.log('refreshToken().pipe called()');
this.setJwtToken(tokens.accessToken);
this.setRefreshToken(tokens.refreshToken);
return true;
})
);
}
logout() {
localStorage.removeItem(this.JWT_TOKEN);
localStorage.removeItem(this.REFRESH_TOKEN);
}
isTokenExpired(): boolean {
const helper = new JwtHelperService();
return helper.isTokenExpired(this.getJwtToken());
}
getJwtToken(): string {
return localStorage.getItem(this.JWT_TOKEN);
}
setJwtToken(token: string) {
localStorage.setItem(this.JWT_TOKEN, token);
}
getRefreshToken(): string {
return localStorage.getItem(this.REFRESH_TOKEN);
}
setRefreshToken(token: string) {
localStorage.setItem(this.REFRESH_TOKEN, token);
}
}
从'@angular/core'导入{Injectable};
从'@angular/common/http'导入{HttpClient};
从'src/environments/environment'导入{environment};
从“rxjs/operators”导入{map};
从'@auth0/jwt'导入{JwtHelperService};
从“../types/user”导入{AccessToken};
@可注射()
导出类身份验证服务{
私有actionUrl:string;
私有只读JWT_令牌='访问_令牌';
私有只读刷新令牌='刷新令牌';
构造函数(私有httpClient:httpClient){
this.actionUrl=`${environment.baseUrls.server}api/auth`;
}
isLoggedIn():布尔值{
return!!this.getJwtToken();
}
登录(凭据:{电子邮件:字符串,密码:字符串}){
返回此.httpClient.post(`${this.actionUrl}/login`,凭证)
.烟斗(
映射(令牌=>{
this.setJwtToken(tokens.accessToken);
this.setRefreshToken(tokens.refreshToken);
返回true;
})
);
}
刷新令牌(){
log('refreshToken()已调用');
const helper=新的JwtHelperService();
const email=helper.decodeToken(this.getJwtToken()).sub;
返回此.httpClient.post(`${this.actionUrl}/token/refresh`,{'refreshToken':localStorage.getItem(this.refresh_token),'email':email})
.烟斗(
映射(令牌=>{
log('refreshToken().pipe called()');
this.setJwtToken(tokens.accessToken);
this.setRefreshToken(tokens.refreshToken);
返回true;
})
);
}
注销(){
localStorage.removietem(这个.JWT_令牌);
localStorage.removietem(此.REFRESH\u令牌);
}
isTokenExpired():布尔值{
const helper=新的JwtHelperService();
return helper.isTokenExpired(this.getJwtToken());
}
getJwtToken():字符串{
返回localStorage.getItem(此.JWT_令牌);
}
setJwtToken(token:string){
setItem(this.JWT_令牌,令牌);
}
getRefreshToken():字符串{
返回localStorage.getItem(此.REFRESH\u令牌);
}
setRefreshToken(标记:字符串){
setItem(this.REFRESH\u令牌,令牌);
}
}
我认为问题就在这里:
else{
console.log('tokenexpired');
//这里!!!
this.authService.refreshToken()
.烟斗(
开关映射(结果=>{
log(`API返回:${result}`);
返回next.handle(this.attachtokentoquest(request,accessToken));
})
);
下一步返回。处理(请求);
}
}
您的是而不是返回的是