![](/img/trans.png)
[英]How to leverage request-promise to request OAuth2 token from Oauth server and include the token in request headers
[英]Angular2: oauth2 with token headers
我是angular2的新手。 在1. *攔截器的一切都很好,只需添加它們:你的標頭到處都有,你可以處理你的請求,當令牌變得無效時......
在angular2
我正在使用RxJs
。 所以我得到了我的令牌:
getToken(login: string, pwd: string): Observable<boolean> {
let bodyParams = {
grant_type: 'password',
client_id: 'admin',
scope: AppConst.CLIENT_SCOPE,
username: login,
password: pwd
};
let params = new URLSearchParams();
for (let key in bodyParams) {
params.set(key, bodyParams[key])
}
let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'});
let options = new RequestOptions({headers: headers});
return this.http.post(AppConst.IDENTITY_BASE_URI + '/connect/token', params.toString(), options)
.map((response: Response) => {
let data = response.json();
if (data) {
this.data = data;
localStorage.setItem('auth', JSON.stringify({
access_token: data.access_token,
refresh_token: data.refresh_token
}));
return true;
} else {
return false;
}
});
}
然后我如何在每個請求中使用此令牌? 我不想在每個請求中設置.header
。 這是一個不好的做法。
然后:例如,當我做任何請求,並獲得401
error時,我如何攔截並獲得新的令牌,然后恢復所有請求,就像它在angular 1
?
我試圖從這里jwt使用JWT
,但是它不符合我的要求,順便說一下第一個角度我正在使用Restangular
- 並且一切都很好(也有手冊上的令牌: https : //github.com/mgonto/restangular #seterrorinterceptor )
您可以擴展默認的http服務並使用擴展版本,也可以創建一個獲取某些參數的方法(如果需要)並返回RequestOptions對象以傳遞默認的http服務。
選項1
您可以創建服務:
@Injectable()
export class HttpUtils {
constructor(private _cookieService: CookieService) { }
public optionsWithAuth(method: RequestMethod, searchParams?: URLSearchParams): RequestOptionsArgs {
let headers = new Headers();
let token = 'fancyToken';
if (token) {
headers.append('Auth', token);
}
return this.options(method, searchParams, headers);
}
public options(method: RequestMethod, searchParams?: URLSearchParams, header?: Headers): RequestOptionsArgs {
let headers = header || new Headers();
if (!headers.has('Content-Type')) {
headers.append('Content-Type', 'application/json');
}
let options = new RequestOptions({headers: headers});
if (method === RequestMethod.Get || method === RequestMethod.Delete) {
options.body = '';
}
if (searchParams) {
options.params = searchParams;
}
return options;
}
public handleError(error: Response) {
return (res: Response) => {
if (res.status === 401) {
// do something
}
return Observable.throw(res);
};
}
}
用法示例:
this._http
.get('/api/customers', this._httpUtils.optionsWithAuth(RequestMethod.Get))
.map(res => <Customer[]>res.json())
.catch(err => this._httpUtils.handleError(err));
此示例使用cookie來存儲和訪問令牌。 您也可以使用參數。
選項2
第二個選項是擴展http服務,例如:
import { Injectable } from '@angular/core';
import { Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
@Injectable()
export class MyHttp extends Http {
constructor (backend: XHRBackend, options: RequestOptions) {
let token = 'fancyToken';
options.headers.set('Auth', token);
super(backend, options);
}
request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
let token = 'fancyToken';
if (typeof url === 'string') {
if (!options) {
options = {headers: new Headers()};
}
options.headers.append('Auth', token);
} else {
url.headers.append('Auth', token);
}
return super.request(url, options).catch(this.handleError(this));
}
private handleError (self: MyHttp) {
return (res: Response) => {
if (res.status === 401) {
// do something
}
return Observable.throw(res);
};
}
}
在你的@NgModule
:
@NgModule({
// other stuff ...
providers: [
{
provide: MyHttp,
useFactory: (backend: XHRBackend, options: RequestOptions) => {
return new MyHttp(backend, options);
},
deps: [XHRBackend, RequestOptions]
}
]
// a little bit more other stuff ...
})
用法:
@Injectable()
class CustomerService {
constructor(private _http: MyHttp) {
}
query(): Observable<Customer[]> {
return this._http
.get('/api/customers')
.map(res => <Customer[]>res.json())
.catch(err => console.log('error', err));
}
}
額外:
如果要使用刷新令牌獲取新令牌,可以執行以下操作:
private handleError (self: MyHttp, url?: string|Request, options?: RequestOptionsArgs) {
return (res: Response) => {
if (res.status === 401 || res.status === 403) {
let refreshToken:string = 'fancyRefreshToken';
let body:any = JSON.stringify({refreshToken: refreshToken});
return super.post('/api/token/refresh', body)
.map(res => {
// set new token
})
.catch(err => Observable.throw(err))
.subscribe(res => this.request(url, options), err => Observable.throw(err));
}
return Observable.throw(res);
};
}
說實話,我沒有測試過這個,但它至少可以為你提供一個起點。
我們通過擴展AuthHttp解決了這個問題。 我們在AuthHttp上添加了一個方法a來動態設置一個新的頭(X-RoleId是一個自定義頭)
declare module 'angular2-jwt' {
interface AuthHttp {
setRoleId(config: {});
}
}
AuthHttp.prototype.setRoleId = function (roleId) {
let jsThis = <any>(this);
jsThis.config.globalHeaders = [
{'Content-Type': 'application/json'},
{'X-RoleId': roleId}
];
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.