Descripción
La mejor solución que he encontrado es anular el XHRBackendestado de respuesta HTTP 401y 403conduce a una acción en particular.
Si maneja su autenticación fuera de su aplicación Angular, podría forzar una actualización de la página actual de modo que se active su mecanismo externo. Detallo esta solución en la implementación a continuación.
También puede reenviar a un componente dentro de su aplicación de modo que su aplicación Angular no se recargue.
Implementación
Angular> 2.3.0
Gracias a @mrgoos, aquí hay una solución simplificada para angular 2.3.0+ debido a una corrección de errores en angular 2.3.0 (consulte el problema https://github.com/angular/angular/issues/11606 ) que extiende directamente el Httpmódulo.
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);
});
}
}
El archivo del módulo ahora solo contiene el siguiente proveedor.
providers: [
{ provide: Http, useClass: AuthenticatedHttpService }
]
Otra solución que utiliza Router y un servicio de autenticación externo se detalla en la siguiente esencia de @mrgoos.
Angular pre-2.3.0
La siguiente implementación funciona para Angular 2.2.x FINALy RxJS 5.0.0-beta.12.
Redirige a la página actual (más un parámetro para obtener una URL única y evitar el almacenamiento en caché) si se devuelve un código 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 el siguiente archivo de módulo.
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 {
}