根据登录状态使用路由器重定向用户

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 标志,它是 truefalse(如果未定义标志,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。

以上是关于根据登录状态使用路由器重定向用户的主要内容,如果未能解决你的问题,请参考以下文章

反应路由器重定向在私有路由中不起作用

Vue路由重定向、别名与导航守卫

codeigniter 301 使用路由器重定向旧网址,并且没有重定向

使用反应路由器重定向

解决 REST 请求后如何重定向用户

反应路由器 - 登录后重定向