This commit is contained in:
Musa Demir 2019-11-12 15:20:27 +03:00
Родитель 4a464dd483
Коммит 25864e5471
2 изменённых файлов: 127 добавлений и 48 удалений

Просмотреть файл

@ -1,11 +1,12 @@
import { Injectable } from '@angular/core';
import { Observable, Subject, of } from 'rxjs';
import { Injectable, Injector } from '@angular/core';
import { Observable, Subject, of, BehaviorSubject } from 'rxjs';
import { MessageService } from './message/message.service';
import { LogService } from './log/log.service';
import { TokenService } from './auth/token.service';
import { UtilsService } from './utils/utils.service';
import { HttpClient, HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { switchMap, filter, take, catchError } from 'rxjs/operators';
import { throwError } from 'rxjs/internal/observable/throwError';
export interface IValidationErrorInfo {
@ -43,6 +44,14 @@ export interface IAjaxResponse {
}
@Injectable()
export abstract class RefreshTokenService {
/**
* Try to authenticate with refresh token and return if auth succeed
*/
abstract tryAuthWithRefreshToken(): Observable<boolean>;
}
@Injectable()
export class AbpHttpConfiguration {
@ -128,9 +137,9 @@ export class AbpHttpConfiguration {
handleAbpResponse(response: HttpResponse<any>, ajaxResponse: IAjaxResponse): HttpResponse<any> {
var newResponse: HttpResponse<any>;
if (ajaxResponse.success) {
newResponse = response.clone({
body: ajaxResponse.result
});
@ -160,7 +169,7 @@ export class AbpHttpConfiguration {
}
getAbpAjaxResponseOrNull(response: HttpResponse<any>): IAjaxResponse | null {
if(!response || !response.headers) {
if (!response || !response.headers) {
return null;
}
@ -174,7 +183,7 @@ export class AbpHttpConfiguration {
this._logService.warn('Content-Type is not application/json: ' + contentType);
return null;
}
var responseObj = JSON.parse(JSON.stringify(response.body));
if (!responseObj.__abp) {
return null;
@ -198,12 +207,12 @@ export class AbpHttpConfiguration {
observer.next("");
observer.complete();
} else {
let reader = new FileReader();
reader.onload = function() {
let reader = new FileReader();
reader.onload = function () {
observer.next(this.result);
observer.complete();
}
reader.readAsText(blob);
reader.readAsText(blob);
}
});
}
@ -211,37 +220,91 @@ export class AbpHttpConfiguration {
@Injectable()
export class AbpHttpInterceptor implements HttpInterceptor {
protected configuration: AbpHttpConfiguration;
private _tokenService: TokenService = new TokenService();
private _utilsService: UtilsService = new UtilsService();
private _logService: LogService = new LogService();
constructor(configuration: AbpHttpConfiguration) {
constructor(configuration: AbpHttpConfiguration,
private _injector: Injector) {
this.configuration = configuration;
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
var interceptObservable = new Subject<HttpEvent<any>>();
var modifiedRequest = this.normalizeRequestHeaders(request);
next.handle(modifiedRequest)
.subscribe((event: HttpEvent<any>) => {
this.handleSuccessResponse(event, interceptObservable );
}, (error: any) => {
return this.handleErrorResponse(error, interceptObservable);
});
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return interceptObservable;
}
var interceptObservable = new Subject<HttpEvent<any>>();
var modifiedRequest = this.normalizeRequestHeaders(request);
next.handle(modifiedRequest)
.pipe(
catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.tryAuthWithRefreshToken(request, next, error);
} else {
return throwError(error);
}
})
).subscribe(
(event: HttpEvent<any>) => {
this.handleSuccessResponse(event, interceptObservable);
},
(error: any) => {
return this.handleErrorResponse(error, interceptObservable);
}
);
protected normalizeRequestHeaders(request: HttpRequest<any>):HttpRequest<any> {
return interceptObservable;
}
protected tryGetRefreshTokenService(): Observable<boolean> {
try {
var _refreshTokenService = this._injector.get(RefreshTokenService);
if (_refreshTokenService) {
return _refreshTokenService.tryAuthWithRefreshToken();
}
} catch (error) {
return of(false);
}
return of(false);
}
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
private tryAuthWithRefreshToken(request: HttpRequest<any>, next: HttpHandler, error: any) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.tryGetRefreshTokenService().pipe(
switchMap((authResult: boolean) => {
this.isRefreshing = false;
if (authResult) {
this.refreshTokenSubject.next(authResult);
let modifiedRequest = this.normalizeRequestHeaders(request);
return next.handle(modifiedRequest);
} else {
return throwError(error);
}
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(authResult => {
let modifiedRequest = this.normalizeRequestHeaders(request);
return next.handle(modifiedRequest);
}));
}
}
protected normalizeRequestHeaders(request: HttpRequest<any>): HttpRequest<any> {
var modifiedHeaders = new HttpHeaders();
modifiedHeaders = request.headers.set("Pragma","no-cache")
.set("Cache-Control","no-cache")
.set("Expires", "Sat, 01 Jan 2000 00:00:00 GMT");
modifiedHeaders = request.headers.set("Pragma", "no-cache")
.set("Cache-Control", "no-cache")
.set("Expires", "Sat, 01 Jan 2000 00:00:00 GMT");
modifiedHeaders = this.addXRequestedWithHeader(modifiedHeaders);
modifiedHeaders = this.addAuthorizationHeaders(modifiedHeaders);
modifiedHeaders = this.addAspNetCoreCultureHeader(modifiedHeaders);
@ -253,7 +316,7 @@ export class AbpHttpInterceptor implements HttpInterceptor {
});
}
protected addXRequestedWithHeader(headers:HttpHeaders):HttpHeaders {
protected addXRequestedWithHeader(headers: HttpHeaders): HttpHeaders {
if (headers) {
headers = headers.set('X-Requested-With', 'XMLHttpRequest');
}
@ -261,7 +324,7 @@ export class AbpHttpInterceptor implements HttpInterceptor {
return headers;
}
protected addAspNetCoreCultureHeader(headers:HttpHeaders):HttpHeaders {
protected addAspNetCoreCultureHeader(headers: HttpHeaders): HttpHeaders {
let cookieLangValue = this._utilsService.getCookieValue("Abp.Localization.CultureName");
if (cookieLangValue && headers && !headers.has('.AspNetCore.Culture')) {
headers = headers.set('.AspNetCore.Culture', cookieLangValue);
@ -270,7 +333,7 @@ export class AbpHttpInterceptor implements HttpInterceptor {
return headers;
}
protected addAcceptLanguageHeader(headers:HttpHeaders):HttpHeaders {
protected addAcceptLanguageHeader(headers: HttpHeaders): HttpHeaders {
let cookieLangValue = this._utilsService.getCookieValue("Abp.Localization.CultureName");
if (cookieLangValue && headers && !headers.has('Accept-Language')) {
headers = headers.set('Accept-Language', cookieLangValue);
@ -279,7 +342,7 @@ export class AbpHttpInterceptor implements HttpInterceptor {
return headers;
}
protected addTenantIdHeader(headers:HttpHeaders):HttpHeaders {
protected addTenantIdHeader(headers: HttpHeaders): HttpHeaders {
let cookieTenantIdValue = this._utilsService.getCookieValue(abp.multiTenancy.tenantIdCookieName);
if (cookieTenantIdValue && headers && !headers.has(abp.multiTenancy.tenantIdCookieName)) {
headers = headers.set(abp.multiTenancy.tenantIdCookieName, cookieTenantIdValue);
@ -288,8 +351,8 @@ export class AbpHttpInterceptor implements HttpInterceptor {
return headers;
}
protected addAuthorizationHeaders(headers:HttpHeaders): HttpHeaders {
let authorizationHeaders = headers ? headers.getAll('Authorization'): null;
protected addAuthorizationHeaders(headers: HttpHeaders): HttpHeaders {
let authorizationHeaders = headers ? headers.getAll('Authorization') : null;
if (!authorizationHeaders) {
authorizationHeaders = [];
}
@ -304,22 +367,22 @@ export class AbpHttpInterceptor implements HttpInterceptor {
return headers;
}
protected handleSuccessResponse(event: HttpEvent<any>, interceptObservable: Subject<HttpEvent<any>>): void{
protected handleSuccessResponse(event: HttpEvent<any>, interceptObservable: Subject<HttpEvent<any>>): void {
var self = this;
if (event instanceof HttpResponse) {
if (event.body instanceof Blob && event.body.type && event.body.type.indexOf("application/json") >= 0){
if (event.body instanceof Blob && event.body.type && event.body.type.indexOf("application/json") >= 0) {
var clonedResponse = event.clone();
self.configuration.blobToText(event.body).subscribe(json => {
const responseBody = json == "null" ? {}: JSON.parse(json);
const responseBody = json == "null" ? {} : JSON.parse(json);
var modifiedResponse = self.configuration.handleResponse(event.clone({
body: responseBody
}));
interceptObservable.next(modifiedResponse.clone({
body: new Blob([JSON.stringify(modifiedResponse.body)], {type : 'application/json'})
body: new Blob([JSON.stringify(modifiedResponse.body)], { type: 'application/json' })
}));
interceptObservable.complete();
@ -336,14 +399,14 @@ export class AbpHttpInterceptor implements HttpInterceptor {
protected handleErrorResponse(error: any, interceptObservable: Subject<HttpEvent<any>>): Observable<any> {
var errorObservable = new Subject<any>();
if(!(error.error instanceof Blob)){
if (!(error.error instanceof Blob)) {
interceptObservable.error(error);
interceptObservable.complete();
return of({});
}
this.configuration.blobToText(error.error).subscribe(json => {
const errorBody = (json == "" || json == "null") ? {}: JSON.parse(json);
const errorBody = (json == "" || json == "null") ? {} : JSON.parse(json);
const errorResponse = new HttpResponse({
headers: error.headers,
status: error.status,
@ -351,7 +414,7 @@ export class AbpHttpInterceptor implements HttpInterceptor {
});
var ajaxResponse = this.configuration.getAbpAjaxResponseOrNull(errorResponse);
if (ajaxResponse != null) {
this.configuration.handleAbpResponse(errorResponse, ajaxResponse);
} else {
@ -359,11 +422,11 @@ export class AbpHttpInterceptor implements HttpInterceptor {
}
errorObservable.complete();
interceptObservable.error(error);
interceptObservable.complete();
});
return errorObservable;
}

Просмотреть файл

@ -19,4 +19,20 @@ export class TokenService {
abp.auth.setToken(authToken, expireDate);
}
//refresh token
getRefreshToken(): string {
return abp.auth.getRefreshToken();
}
getRefreshTokenCookieName(): string {
return abp.auth.refreshTokenCookieName;
}
clearRefreshToken(): void {
abp.auth.clearRefreshToken();
}
setRefreshToken(refreshToken: string, expireDate?: Date): void {
abp.auth.setRefreshToken(refreshToken, expireDate);
}
}