navigationend - Angular2: Global Guard(el usuario debe estar conectado siempre)
singleton angular 4 service (2)
Creo que lo hago de una manera mucho más lógica. Supongo que es una opinión. Separa mi aplicación por secured pages
y public pages
. Yo uso plantillas para cada conjunto. Entonces, public component
y secure component
ponen el guard
sobre la secure template
.
Asegúrese de agregar [Guard]
a la ruta completa que necesita protección.
Entonces, cuando aseguro una ruta, agrego los padres a app.routing.ts
const APP_ROUTES: Routes = [
{ path: '''', redirectTo: ''/home'', pathMatch: ''full'', },
{ path: '''', component: PublicComponent, data: { title: ''Public Views'' }, children: PUBLIC_ROUTES },
{ path: '''', component: SecureComponent, canActivate: [Guard], data: { title: ''Secure Views'' }, children: SECURE_ROUTES }
];
export const routing = RouterModule.forRoot(APP_ROUTES);
Asegúrate de que esta línea se note,
{ path: '''', component: SecureComponent, canActivate: [Guard], data: { title: ''Secure Views'' }, children: SECURE_ROUTES }
Entonces creo 2 diseños
/ público / todos los componentes públicos
/public/public.routes.ts
/ seguro / todos los componentes seguros
/secure/secure.routes.ts
Rutas seguras
Tenga en cuenta que estas rutas no necesitan Guard
ahora porque la maneja la plantilla principal.
export const SECURE_ROUTES: Routes = [
{ path: '''', redirectTo: ''overview'', pathMatch: ''full'' },
{ path: ''items'', component: ItemsComponent },
{ path: ''overview'', component: OverviewComponent },
{ path: ''profile'', component: ProfileComponent },
];
Principales rutas en app.routing.ts
const APP_ROUTES: Routes = [
{ path: '''', redirectTo: ''/home'', pathMatch: ''full'', },
{ path: '''', component: PublicComponent, data: { title: ''Public Views'' }, children: PUBLIC_ROUTES },
{ path: '''', component: SecureComponent, canActivate: [Guard], data: { title: ''Secure Views'' }, children: SECURE_ROUTES }
];
export const routing = RouterModule.forRoot(APP_ROUTES);
Y en el directorio / diseños, creo un diseño que es
/layouts/secure.component.ts
/layouts/secure.component.html
/layouts/public.component.ts
/layouts/public.component.html
Todo se enruta a través del diseño public
o secure
y [Guard]
está seguro.
Luego manejo la autenticación con un token en el almacenamiento local.
@Injectable()
export class Guard implements CanActivate {
constructor(protected router: Router, protected auth: Auth ) {}
canActivate() {
if (localStorage.getItem(''access_token'')) {
// logged in so return true
return true;
}
// not logged in so redirect to login page
this.router.navigate([''/home'']);
return false;
}
}
Una vez que configuro mi aplicación de esta manera, puse todas las rutas que deben estar seguras en el directorio seguro y las rutas públicas en público. Luego creo sus rutas en el archivo public.routes.ts o en el archivo secure.routes.ts que están en su directorio respectivo.
Estoy construyendo una aplicación donde no hay acceso para usuarios no autenticados.
Escribí un LoggedInGuard
, pero ahora tengo que agregar canActivate: [LoggedInGuard]
a cada ruta dentro de la configuración de mi enrutador (excepto el LoginComponent
).
¿Hay una mejor manera de hacer que esto funcione?
El diseño de mi archivo / módulo se ve así:
app/
AppModule
AppRoutingModule
AppComponent
authentication/
AuthenticationModule
AuthenticationRoutingModule
LoginComponent
contacts/
ContactsModule
ContactsRoutingModule
ContactListComponent
users/
UsersModule
UsersRoutingModule
UserEditComponent
...
Tal vez sea posible crear dos espacios de enrutamiento separados (uno para iniciar sesión, otro para el resto de la aplicación) y aplicar el protector solo al resto de la parte de la aplicación .
Espero que haya una solución simple.
¡Gracias por adelantado!
Pude proporcionar un conjunto de protecciones globales que abarcaban múltiples módulos al mover las guardias a un detector de eventos de enrutador.
Para que el detector de eventos active todas las solicitudes, lo inserté en el componente de aplicación.
Tenga en cuenta que, en ambos ejemplos a continuación, aún puede agregar guardias personalizados para rutas individuales, y eso seguirá funcionando.
Sin guardias
Puede eliminar el uso de guardias y, en su lugar, implementar la lógica directamente en el detector de eventos.
import { Component, OnInit } from ''@angular/core'';
import { Router, RoutesRecognized } from ''@angular/router'';
import { Observable } from ''rxjs/Observable'';
import ''rxjs/add/operator/filter'';
// I use a service to keep track of the authentication ticket.
// Replace this with whatever mechanism you use.
import { AuthenticationService } from ''./_services/index'';
@Component({
selector: ''app-root'',
templateUrl: ''./app.component.html'',
styleUrls: [''./app.component.css'']
})
export class AppComponent implements OnInit {
constructor(
private router: Router,
private authService: AuthenticationService
) {}
ngOnInit() {
this.router.events
.filter(event => event instanceof RoutesRecognized)
.subscribe((event: RoutesRecognized) => {
const url = event.urlAfterRedirects;
// Public URLs don''t need any kind of authorization.
if (url === ''/public'' || url.startsWith(''/public/'') || url.startsWith(''/public?'')) {
return;
}
// Everything else must be authenticated.
if (!this.authService.isAuthenticated()) {
// Allow for the login page to redirect back to the originally
// requested page.
this.router.navigate([''/public/login''], { queryParams: { returnUrl: state.url } });
}
});
}
}
Las solicitudes que se pasan a cualquier subpágina de /public
pasarán independientemente, pero cualquier otra solicitud debe tener autenticación, o se redirigirá a /public/login
.
Tenga cuidado de que la página de redirección no se encuentre en el área protegida, de lo contrario, el enrutador ingresará un bucle infinito.
Con guardias
La implementación a continuación muestra cómo reutilicé las guardias existentes. Esto es solo si necesita conservarlos, o si hace que su código sea más limpio.
import { Component, OnInit } from ''@angular/core'';
import { Router, ActivatedRoute, RoutesRecognized, CanActivate } from ''@angular/router'';
import { Observable } from ''rxjs/Observable'';
import ''rxjs/add/operator/filter'';
import ''rxjs/add/operator/map'';
import ''rxjs/add/operator/mergeMap'';
// Reused guards.
import { AdminGuard, AuthGuard } from ''./_guards/index'';
@Component({
selector: ''app-root'',
templateUrl: ''./app.component.html'',
styleUrls: [''./app.component.css'']
})
export class AppComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private router: Router,
private adminGuard: AdminGuard,
private authGuard: AuthGuard
) {}
ngOnInit() {
this.router.events
.filter(event => event instanceof RoutesRecognized)
.subscribe((event: RoutesRecognized) => {
// Public pages don''t require authentication.
if (this.isSubPage(event, ''/public'')) {
return;
}
// All other requests MUST be done through an
// authenticated connection. The guard performs
// the redirection for us.
if (!this.callCanActivate(event, this.authGuard)) {
return;
}
// Administration pages require additional restrictions.
// The guard performs the redirection for us.
if (this.isSubPage(event, ''/admin'')) {
if (!this.callCanActivate(event, this.adminGuard)) {
return;
}
}
});
}
callCanActivate(event: RoutesRecognized, guard: CanActivate) {
return guard.canActivate(this.route.snapshot, event.state);
}
isSubPage(event: RoutesRecognized, parent: string) {
const url = event.urlAfterRedirects;
return (url === parent
|| url.startsWith(parent + ''/'')
|| url.startsWith(parent + ''?''));
}
}
Este ejemplo es el mismo que el anterior, pero con protección adicional para el área /admin
, lo que garantiza que el usuario también tenga permisos administrativos.