La description
La meilleure solution que j'ai trouvée est de remplacer le XHRBackend
tel que l'état de la réponse HTTP 401
et 403
conduit à une action particulière.
Si vous gérez votre authentification en dehors de votre application Angular, vous pouvez forcer une actualisation de la page actuelle de sorte que votre mécanisme externe se déclenche. Je détaille cette solution dans l'implémentation ci-dessous.
Vous pouvez également transférer vers un composant de votre application afin que votre application Angular ne soit pas rechargée.
la mise en oeuvre
Angulaire> 2,3,0
Grâce à @mrgoos, voici une solution simplifiée pour angular 2.3.0+ en raison d'un bug corrigé dans angular 2.3.0 (voir issue https://github.com/angular/angular/issues/11606 ) étendant directement le Http
module.
import { Injectable } from '@angular/core';
import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class AuthenticatedHttpService extends Http {
constructor(backend: XHRBackend, defaultOptions: RequestOptions) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return super.request(url, options).catch((error: Response) => {
if ((error.status === 401 || error.status === 403) && (window.location.href.match(/\?/g) || []).length < 2) {
console.log('The authentication session expires or the user is not authorised. Force refresh of the current page.');
window.location.href = window.location.href + '?' + new Date().getMilliseconds();
}
return Observable.throw(error);
});
}
}
Le fichier de module contient désormais uniquement le fournisseur suivant.
providers: [
{ provide: Http, useClass: AuthenticatedHttpService }
]
Une autre solution utilisant Router et un service d'authentification externe est détaillée dans l' essentiel suivant par @mrgoos.
Angulaire pré-2.3.0
L'implémentation suivante fonctionne pour Angular 2.2.x FINAL
et RxJS 5.0.0-beta.12
.
Il redirige vers la page actuelle (plus un paramètre pour obtenir une URL unique et éviter la mise en cache) si un code HTTP 401 ou 403 est renvoyé.
import { Request, XHRBackend, BrowserXhr, ResponseOptions, XSRFStrategy, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
export class AuthenticationConnectionBackend extends XHRBackend {
constructor(_browserXhr: BrowserXhr, _baseResponseOptions: ResponseOptions, _xsrfStrategy: XSRFStrategy) {
super(_browserXhr, _baseResponseOptions, _xsrfStrategy);
}
createConnection(request: Request) {
let xhrConnection = super.createConnection(request);
xhrConnection.response = xhrConnection.response.catch((error: Response) => {
if ((error.status === 401 || error.status === 403) && (window.location.href.match(/\?/g) || []).length < 2) {
console.log('The authentication session expires or the user is not authorised. Force refresh of the current page.');
window.location.href = window.location.href + '?' + new Date().getMilliseconds();
}
return Observable.throw(error);
});
return xhrConnection;
}
}
avec le fichier de module suivant.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule, XHRBackend } from '@angular/http';
import { AppComponent } from './app.component';
import { AuthenticationConnectionBackend } from './authenticated-connection.backend';
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
],
entryComponents: [AppComponent],
imports: [
BrowserModule,
CommonModule,
HttpModule,
],
providers: [
{ provide: XHRBackend, useClass: AuthenticationConnectionBackend },
],
})
export class AppModule {
}