Descrizione
La soluzione migliore che ho trovato è sovrascrivere XHRBackend
tale che lo stato della risposta HTTP 401
e 403
porti a una particolare azione.
Se gestisci la tua autenticazione al di fuori della tua applicazione Angular, potresti forzare un aggiornamento della pagina corrente in modo che il tuo meccanismo esterno venga attivato. Descrivo in dettaglio questa soluzione nell'implementazione di seguito.
Puoi anche inoltrare a un componente all'interno della tua applicazione in modo che la tua applicazione Angular non venga ricaricata.
Implementazione
Angolare> 2.3.0
Grazie a @mrgoos, ecco una soluzione semplificata per angular 2.3.0+ a causa di una correzione di bug in angular 2.3.0 (vedi problema https://github.com/angular/angular/issues/11606 ) che estende direttamente il Http
modulo.
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);
});
}
}
Il file del modulo ora contiene solo il seguente provider.
providers: [
{ provide: Http, useClass: AuthenticatedHttpService }
]
Un'altra soluzione utilizzando router e un servizio di autenticazione esterna è dettagliata nella seguente Gist da @mrgoos.
Angolare pre-2.3.0
La seguente implementazione funziona per Angular 2.2.x FINAL
e RxJS 5.0.0-beta.12
.
Reindirizza alla pagina corrente (più un parametro per ottenere un URL univoco ed evitare la memorizzazione nella cache) se viene restituito un codice HTTP 401 o 403.
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;
}
}
con il seguente file di modulo.
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 {
}