根据登录状态使用路由器重定向用户
Posted
技术标签:
【中文标题】根据登录状态使用路由器重定向用户【英文标题】:Redirect user with router depending on logged in status 【发布时间】:2017-06-14 19:36:24 【问题描述】:如果用户未登录,我想自动路由到登录页面。
app.module.ts
import RouterModule, Routes from '@angular/router';
import AppComponent from './app.component';
import LoginComponent from './login/login.component';
import DashBoardComponent from './dashboard/dashboard.component';
import NotFoundComponent from './not-found/not-found.component';
const APPROUTES: Routes = [
path: 'home', component: AppComponent,
path: 'login', component: LoginComponent,
path: 'dashboard', component: DashboardComponent,
path: '**', component: NotFoundComponent
];
@NgModule(
declarations: [
AppComponent,
LoginComponent,
DashboardComponent
NotFoundComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
MaterialModule.forRoot(),
RouterModule.forRoot(APPROUTES)
],
providers: [],
bootstrap: [AppComponent]
)
如果用户未登录,则应加载 LoginComponent
,否则加载 DashboardComponent
。
【问题讨论】:
这个答案可能有用:***.com/a/59008239/7059557 【参考方案1】:你也可以这样做:
path: 'home',
component: getHomeComponent(),
data: requiresLogin: true ,
canActivate: [ AccessGuard ]
然后:
export function getHomeComponent(): Type<Component>
if (User.isLoggedIn)
return <Type<Component>>HomeComponent;
else
return <Type<Component>>LoginComponent;
【讨论】:
【参考方案2】:这里有 3 种方法可以满足您的要求,从最不喜欢到最喜欢:
选项 1. 强制重定向用户 AppComponent
@Component(
selector: 'app-root',
template: `...`
)
export class AppComponent
constructor(authService: AuthService, router: Router)
if (authService.isLoggedIn())
router.navigate(['dashboard']);
不是很好。最好将“需要登录”信息保留在它所属的路由声明中。
选项 2。使用CanActivate
保护
为所有需要用户登录的路由添加CanActivate
保护:
const APPROUTES: Routes = [
path: 'home', component: AppComponent, canActivate:[LoginActivate],
path: 'dashboard', component: DashBoardComponent, canActivate:[LoginActivate],
path: 'login', component: LoginComponent,
path: '**', component: NotFoundComponent
];
我的守卫叫LoginActivate
。
为了让它工作,我必须将保护添加到我的模块的providers
。
然后我需要实现它。在此示例中,如果用户未登录,我将使用守卫重定向用户:
@Injectable()
export class LoginActivate implements CanActivate
constructor(private authService: AuthService, private router: Router)
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean
if (!this.authService.isLoggedIn())
this.router.navigate(['login']);
return true;
如果这没有意义,请查看有关路由保护的文档:https://angular.io/docs/ts/latest/guide/router.html#guards
此选项更好,但不是超级灵活。如果我们需要检查“登录”以外的其他条件,例如用户权限怎么办?如果我们需要向守卫传递一些参数,比如角色名称“admin”、“editor”...?
选项 3. 使用路由 data
属性
恕我直言,最好的解决方案是在路由声明中添加一些元数据以指示“此路由需要用户登录”。
我们可以为此使用路由data
属性。它可以保存任意数据,在这种情况下,我选择包含 requiresLogin
标志,它是 true
或 false
(如果未定义标志,false
将是默认值):
const APPROUTES: Routes = [
path: 'home', component: AppComponent, data:requiresLogin: true,
path: 'dashboard', component: DashBoardComponent, data:requiresLogin: true
];
现在data
属性本身并没有做任何事情。但我可以用它来执行我的“需要登录”逻辑。为此,我再次需要CanActivate
守卫。
太糟糕了,你说。现在我需要为每条受保护的路由添加两件事:元数据和守卫......
但是:
您可以将CanActivate
守卫附加到***路由,它将对其所有子路由执行 [待确认]。这样你只需要使用一次防护。当然,它只有在要保护的路由都是父路由的子路由时才有效(在 Rafael Moura 的示例中并非如此)。
data
属性允许我们将各种参数传递给守卫,例如特定角色的名称或检查权限、用户访问页面所需的点数或积分等。
考虑到这些备注,最好将守卫重命名为更通用的名称,例如AccessGuard
。
我将只显示守卫检索附加到路由的data
的代码段,因为您在守卫内部执行的操作实际上取决于您的情况:
@Injectable()
export class AccessGuard implements CanActivate
canActivate(route: ActivatedRouteSnapshot): Observable<boolean>|Promise<boolean>|boolean
const requiresLogin = route.data.requiresLogin || false;
if (requiresLogin)
// Check that the user is logged in...
上面要执行的代码,需要有类似这样的路由:
path: 'home',
component: AppComponent,
data: requiresLogin: true ,
canActivate: [ AccessGuard ]
注意。不要忘记将AccessGuard
添加到您模块的providers
。
【讨论】:
好的朋友,我要去学习并申请这种方式并提供反馈好的谢谢 如果用户已经登录,选项 2 和 3 如何支持将用户转发到仪表板?据我了解,守卫可以阻止访问组件,但选项 1 允许在用户已获得授权的情况下进行重定向 我不赞成您的选项 2,在主页上设置保护。因为如果你使用主页的预渲染,你无法检查用户是否登录,你会得到闪烁(主页预览>导航页面被保护返回)。 Guard用于限制访问页面,而不是重定向到另一个页面。 注意! ;-) 仅供参考,官方文档有几个 examples 的守卫重定向用户。 我完全同意您的偏好,除了一个例外,如果整个应用程序应该只对登录用户开放,我更喜欢选项 1。以上是关于根据登录状态使用路由器重定向用户的主要内容,如果未能解决你的问题,请参考以下文章