Ben*_*n M 9 angular2-routing angular2-guards angular
我正在构建一个应用程序,对于未经身份验证的用户,根本无法访问.
我写了一个LoggedInGuard,但现在我必须添加canActivate: [LoggedInGuard]到我的路由器配置中的每个路由(除了LoginComponent).
有没有更好的方法让这个工作?
我的文件/模块布局如下所示:
app/
AppModule
AppRoutingModule
AppComponent
authentication/
AuthenticationModule
AuthenticationRoutingModule
LoginComponent
contacts/
ContactsModule
ContactsRoutingModule
ContactListComponent
users/
UsersModule
UsersRoutingModule
UserEditComponent
...
Run Code Online (Sandbox Code Playgroud)
也许可以创建两个单独的路由空间(一个用于登录,一个用于应用程序的其余部分)并且仅将防护应用于应用程序部分的其余部分?
我希望有一个简单的解决方案.
提前致谢!
我想我是以更合乎逻辑的方式做到的.我想这是一个意见.我用secured pages和分开我的申请public pages.我为每一组使用模板.所以public component,secure component然后把它guard放在上面secure template.
确保添加[Guard]到需要保护的完整路径.
因此,当我确保路线时,我将父母添加到 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);
Run Code Online (Sandbox Code Playgroud)
确保注意到这一行,
{ path: '', component: SecureComponent, canActivate: [Guard], data: { title: 'Secure Views' }, children: SECURE_ROUTES }
Run Code Online (Sandbox Code Playgroud)
所以我创建了2个布局
/ public /所有公共组件
/public/public.routes.ts
/ secure /所有安全组件
/secure/secure.routes.ts
安全的路线
请注意,这些路由现在不需要,Guard因为它由模板父进程处理.
export const SECURE_ROUTES: Routes = [
{ path: '', redirectTo: 'overview', pathMatch: 'full' },
{ path: 'items', component: ItemsComponent },
{ path: 'overview', component: OverviewComponent },
{ path: 'profile', component: ProfileComponent },
];
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
在目录/布局中,我创建了一个布局
/layouts/secure.component.ts
/layouts/secure.component.html
/layouts/public.component.ts
/layouts/public.component.html
一切都是通过布局布线public或secure与[Guard]是安全的.
然后我使用本地存储中的令牌处理身份验证.
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
一旦我像这样设置我的应用程序,我将所有需要安全的路由放在安全目录和公共路径中.然后我在public.routes.ts文件或secure.routes.ts文件中创建它们各自的目录中的路由.
小智 6
通过将守卫移动到路由器事件侦听器中,我能够提供一组跨多个模块的全局守卫。
为了使事件侦听器触发所有请求,我将其插入到 AppComponent 中。
请注意,在下面的两个示例中,您仍然可以为各个路由添加自定义防护,并且这些防护仍然有效。
没有守卫
您可以删除对防护的使用,而是直接在事件侦听器中实现逻辑。
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 } });
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
传递到 的任何子页面的请求都/public将通过,但任何其他请求都必须进行身份验证,否则将重定向到/public/login。
注意重定向页面不要在受保护的区域内,否则路由器将进入无限循环。
带卫兵
下面的实现展示了我如何重用现有的守卫。仅当您需要保留它们或者它使您的代码更清晰时才这样做。
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 + '?'));
}
}
Run Code Online (Sandbox Code Playgroud)
此示例与上面的示例相同,但增加了对该/admin区域的保护,这确保了用户还具有管理权限。