在过去两天中,我使用Angular 6尝试了许多不同的方法,最近发布的内容为https://stackoverflow.com/a/47401544。但是,仍未根据请求设置标头。
import {Inject, Injectable} from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpErrorResponse,
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).do((event: HttpEvent<any>) => {
if (localStorage.getItem('id_token') != null) {
// Clone the request to add the new header.
const request = req.clone({
setHeaders: {
'Content-Type' : 'application/json; charset=utf-8',
'Accept' : 'application/json',
'Authorization': `Bearer ${localStorage.getItem('id_token')}`
}
});
return next.handle(request);
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
console.log('redirect auth interceptor')
// do a redirect
}
}
});
}
}
如果我注销request
,则request.headers.lazyUpdate
数组将更新3个项目,但在拦截的请求中看不到Authorization
标头。
request.headers.lazyUpdate
:
{name: "Content-Type", value: "application/json; charset=utf-8", op: "s"}
{name: "Accept", value: "application/json", op: "s"}
{name: "Authorization", value: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2Mzh9.tLTmPK46NhXSuqoCfZKgZcrQWzlNqLMI71-G0iy3bi8", op: "s"}
({request.headers.headers
为空-这可能是问题吗?)
app.module.ts:
providers: [
{provide: HTTP_INTERCEPTORS, useClass: AuthTokenInterceptor, multi: true},
],
使我认为这是一个拦截器问题,如果我将标头手动添加到请求中,则不会得到401
,并且请求将返回正确的数据和一个200
:
return this.http.get(environment.API_URL + 'list/supervise/' + encodeURIComponent(id),
{headers: new HttpHeaders().set('Authorization', `Bearer ${localStorage.getItem('id_token')}`)}).pipe(
map((res: any) => res.data)
);
我有什么可以忽略的吗?谢谢。
编辑:
正如我在下面的评论中提到的,我两次返回next.handle
。这是我最终选择的解决方案:
import {Injectable} from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = localStorage.getItem('id_token');
req = req.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
},
});
return next.handle(req);
}
}
答案 0 :(得分:1)
我使用的完整解决方案:
import {Injectable} from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class AuthTokenInterceptor implements HttpInterceptor {
constructor() {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = localStorage.getItem('id_token');
req = req.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
},
});
return next.handle(req);
}
}
答案 1 :(得分:0)
所以我在这里看到的第一个问题是,如果localStorage中没有值,则您不返回。我会这样构造拦截器:
export class AuthInterceptor implements HttpInterceptor {
private APIToken = null;
private defaultApplicationHeaders = {
'Content-Type': 'application/json'
}
buildRequestHeaders():HttpHeaders {
let headers = this.defaultApplicationHeaders;
// set API-Token if available
if(this.APIToken !== null) {
let authHeaderTpl = `Bearer ${this.APIToken}`;
headers['Authorization'] = authHeaderTpl
}
return new HttpHeaders(headers);
}
constructor() {
this.APIToken = localStorage.getItem('id_token')
}
intercept(req: HttpRequest<any>, next: HttpHandler) {
const headers = this.buildRequestHeaders();
const authReq = req.clone({ headers });
return next.handle(authReq);
}
}
答案 2 :(得分:0)
您可以尝试使用它的简单版本。(just like your reference link does
)
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const jwt = localStorage.getItem('id_token');
if (!!jwt) {
req = req.clone({
setHeaders: {
Authorization: `Bearer ${jwt}`
}
});
}
return next.handle(req);
}
您不必在这里处理error
因为intercepter
在这里(根据您的情况)是指向 clone (克隆)(这意味着每当我们收到请求时,我们都会对其进行克隆,然后执行我们想要的任何操作并将其发送出去)。
我们可以为更多的标头添加更多的数据
它将被发送出去,然后最终从Api返回并返回
将句柄问题留给调用service
的{{1}}(例如:httpRequest
,...)。
再次,您在then, catch, pipe
中声明了这一点,这意味着app.module.ts
中应用程序中api的all
将被拦截,如果我想处理一个带有错误的特定请求该怎么办消息request
?,如果您执行一些复杂的逻辑,则可能会影响所有请求。
关于上面的代码,我还没有尝试过,但是我认为当您这样嵌套时,它们可能是发生了错误,应该将断点放在它们的位置并尝试调试发生的事情。
答案 3 :(得分:0)
对于那些关注msal角MsalHttpInterceptor的人。
现在,我自己实现了MsalInterceptor。
这是我的自定义代码块:
// #region own workaround in order not to put every api endpoint url to settings
if (!scopes && req.url.startsWith(this.settingsService.apiUrl)) {
scopes = [this.auth.getCurrentConfiguration().auth.clientId];
}
// #endregion
// If there are no scopes set for this request, do nothing.
if (!scopes) {
return next.handle(req);
}
PS:为protectedResourceMap https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/1776
中的通配符投票