import {Directive, OnDestroy} from 'angular2/core';
import {AuthService} from '../services/auth.service';
import {ROUTER_DIRECTIVES, Router, Location} from "angular2/router";
@Directive({
selector: '[protected]'
})
export class ProtectedDirective implements OnDestroy {
private sub:any = null;
constructor(private authService:AuthService, private router:Router, private location:Location) {
if (!authService.isAuthenticated()) {
this.location.replaceState('/'); // clears browser history so they can't navigate with back button
this.router.navigate(['PublicPage']);
}
this.sub = this.authService.subscribe((val) => {
if (!val.authenticated) {
this.location.replaceState('/'); // clears browser history so they can't navigate with back button
this.router.navigate(['LoggedoutPage']); // tells them they've been logged out (somehow)
}
});
}
ngOnDestroy() {
if (this.sub != null) {
this.sub.unsubscribe();
}
}
}
这使用我编写的身份验证服务来确定用户是否已经登录并且 also subscribes 到身份验证事件,以便在用户注销或超时时可以将用户踢出 .
你可以做同样的事情 . 您'd create a directive like mine that checks for the presence of a necessary cookie or other state information that indicates that the user is authenticated. If they don' t有您正在寻找的那些标志,将用户重定向到您的主公共页面(就像我这样)或您的OAuth2服务器(或其他) . 您可以将该指令属性放在需要保护的任何组件上 . 在这种情况下,它可能被称为 protected ,就像我上面粘贴的指令一样 .
然后,您可能希望将用户导航/重定向到应用程序中的登录视图,并在那里处理身份验证 . 您'd have to change the current route to the one you wanted to do that. So in that case you' d使用依赖注入在您的指令的 constructor() 函数中获取Router object然后使用 navigate() 方法将用户发送到您的登录页面(如上例所示) .
1. Create a guard as seen below. 2. Install ngx-cookie-service to get cookies returned by external SSO. 3. Create ssoPath in environment.ts (SSO Login redirection). 4. Get the state.url and use encodeURIComponent.
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from
'@angular/router';
import { CookieService } from 'ngx-cookie-service';
import { environment } from '../../../environments/environment.prod';
@Injectable()
export class AuthGuardService implements CanActivate {
private returnUrl: string;
constructor(private _router: Router, private cookie: CookieService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
if (this.cookie.get('MasterSignOn')) {
return true;
} else {
let uri = window.location.origin + '/#' + state.url;
this.returnUrl = encodeURIComponent(uri);
window.location.href = environment.ssoPath + this.returnUrl ;
return false;
}
}
}
7 回答
Usage with the final router
随着新路由器的推出,保护路线变得更加容易 . 您必须定义一个作为服务的防护,并将其添加到路由中 .
现在将
LoggedInGuard
传递给路径,并将其添加到模块的providers
数组中 .模块声明:
关于它如何与最终版本一起使用的详细博客文章:https://medium.com/@blacksonic86/angular-2-authentication-revisited-611bf7373bf9
Usage with the deprecated router
更强大的解决方案是扩展
RouterOutlet
并在激活路由时检查用户是否已登录 . 这样您就不必将指令复制并粘贴到每个组件 . 加上基于子组件的重定向可能会产生误导 .无论用户是否登录,_549085都代表业务逻辑所在的位置 . 您可以使用构造函数中的DI轻松添加它 .
当用户导航到您网站上的新网址时,将使用当前指令调用activate方法 . 从中你可以 grab 网址并决定是否允许 . 如果不只是重定向到登录页面 .
使其工作的最后一件事仍然是将其传递给我们的主要组件而不是内置组件 .
此解决方案不能与
@CanActive
生命周期装饰器一起使用,因为如果传递给它的函数解析为false,则不会调用RouterOutlet
的activate方法 .还写了一篇关于它的详细博客文章:https://medium.com/@blacksonic86/authentication-in-angular-2-958052c64492
Update: 我在Github上发布了一个完整的骨架Angular 2 project with OAuth2 integration,它显示了下面提到的指令 .
一种方法是使用
directive
. 与Angular 2components
(基本上是新的HTML标记(带有相关代码))不同,您插入到页面中,属性指令是您放入标记中的属性,会导致某些行为发生 . Docs here .您的自定义属性的存在会导致您将指令放入的组件(或HTML元素)发生 . 请考虑我用于当前Angular2 / OAuth2应用程序的此指令:
这使用我编写的身份验证服务来确定用户是否已经登录并且 also subscribes 到身份验证事件,以便在用户注销或超时时可以将用户踢出 .
你可以做同样的事情 . 您'd create a directive like mine that checks for the presence of a necessary cookie or other state information that indicates that the user is authenticated. If they don' t有您正在寻找的那些标志,将用户重定向到您的主公共页面(就像我这样)或您的OAuth2服务器(或其他) . 您可以将该指令属性放在需要保护的任何组件上 . 在这种情况下,它可能被称为
protected
,就像我上面粘贴的指令一样 .然后,您可能希望将用户导航/重定向到应用程序中的登录视图,并在那里处理身份验证 . 您'd have to change the current route to the one you wanted to do that. So in that case you' d使用依赖注入在您的指令的
constructor()
函数中获取Router object然后使用navigate()
方法将用户发送到您的登录页面(如上例所示) .这假设您有一系列路径控制
<router-outlet>
标记,看起来像这样,也许:相反,如果您需要将用户重定向到 external URL(例如OAuth2服务器),那么您的指令应该执行以下操作:
请参阅此代码,auth.ts文件
这是使用Angular 4的更新示例
Routes with home route protected by AuthGuard
AuthGuard redirects to login page if user isn't logged in
更新以将查询参数中的原始URL传递到登录页面
有关完整示例和工作演示,您可以查看this post
1. Create a guard as seen below. 2. Install ngx-cookie-service to get cookies returned by external SSO. 3. Create ssoPath in environment.ts (SSO Login redirection). 4. Get the state.url and use encodeURIComponent.
按照上面的精彩答案,我还想
CanActivateChild
:守卫儿童路线 . 它可用于将guard
添加到有助于ACL等情况的子路径中它是这样的
这取自https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard
请不要覆盖路由器插座!这是最新路由器版本(3.0测试版)的噩梦 .
而是使用接口CanActivate和CanDeactivate,并在路由定义中将类设置为canActivate / canDeactivate .
像那样:
类:
另见:https://angular.io/docs/ts/latest/guide/router.html#!#can-activate-guard