使用路由器重定向用户,具体取决于登录状态 [英] Redirect user with router depending on logged in status

查看:100
本文介绍了使用路由器重定向用户,具体取决于登录状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果用户未登录,我想自动转到登录页面.

I would like to automatically route to a login page if the user is not logged in.

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.

If the user isn't logged in, the LoginComponent should load, otherwise the DashboardComponent.

推荐答案

从最不喜欢到最喜欢的三种方法可以按照您的要求进行:

Here are 3 ways to do what you asked, from least preferred to favorite:

选项1.强制在AppComponent

Option 1. Imperatively redirect the user in AppComponent

@Component({
  selector: 'app-root',
  template: `...`
})
export class AppComponent {
  constructor(authService: AuthService, router: Router) {
    if (authService.isLoggedIn()) {
      router.navigate(['dashboard']);
    }
  }
}

不太好.最好将需要登录"信息保留在其所属的路由声明中.

Not very good. It's better to keep the "login required" information in the route declaration where it belongs.

选项2.使用CanActivate防护罩

Option 2. Use a CanActivate guard

为需要用户登录的所有路由添加CanActivate防护:

Add a CanActivate guard to all the routes that require the user to be logged in:

const APPROUTES: Routes = [
  {path: 'home', component: AppComponent, canActivate:[LoginActivate]},
  {path: 'dashboard', component: DashBoardComponent, canActivate:[LoginActivate]},
  {path: 'login', component: LoginComponent},
  {path: '**', component: NotFoundComponent}
];

我的后卫叫LoginActivate.

要使其正常工作,我必须在模块的providers中添加防护装置.

For it to work I must add the guard to my module's providers.

然后我需要实现它.在此示例中,如果用户未登录,我将使用防护来重定向用户:

And then I need to implement it. In this example I'll use the guard to redirect the user if they're not logged in:

@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

Check out the doc about route guards if this doesn't make sense: https://angular.io/docs/ts/latest/guide/router.html#guards

此选项更好,但不是超级灵活.如果我们需要检查登录"之外的其他条件,例如用户权限,该怎么办?如果我们需要将一些参数(例如角色名称"admin","editor" ...)传递给后卫,该怎么办?

This option is better but not super flexible. What if we need to check for other conditions than "logged in" such as the user permissions? What if we need to pass some parameter to the guard, like the name of a role "admin", "editor"...?

选项3.使用路由data属性

Option 3. Use the route data property

恕我直言,最好的解决方案是在路由声明中添加一些元数据,以表明此路由要求用户登录".

The best solution IMHO is to add some metadata in the routes declaration to indicate "this route requires that the user be logged in".

我们可以使用route data属性.它可以保存任意数据,在这种情况下,我选择包含truefalserequiresLogin标志(如果未定义该标志,则默认为false):

We can use the route data property for that. It can hold arbitrary data and in this case I chose to include a requiresLogin flag that's either true or false (false will be the default if the flag is not defined):

const APPROUTES: Routes = [
  {path: 'home', component: AppComponent, data:{requiresLogin: true}},
  {path: 'dashboard', component: DashBoardComponent, data:{requiresLogin: true}}
];

现在,data属性本身不执行任何操作.但是我可以用它来执行我的需要登录"逻辑.为此,我需要一个CanActivate护卫.

Now the data property in itself doesn't do anything. But I can use it to enforce my "login required" logic. For that I need a CanActivate guard again.

太糟糕了,你说.现在,我需要为每个受保护的路由添加2件事:元数据和警卫...

Too bad, you say. Now I need to add 2 things to each protected route: the metadata AND the guard...

但是:

  • 您可以将CanActivate防护罩附加到顶层路由,并且它将对其所有子级路由执行 [需要确认].这样,您只需要使用一次防护罩即可.当然,仅当要保护的路由是父路由的所有子路由时才起作用(在拉斐尔·莫拉(Rafael Moura)的示例中不是这种情况).
  • data属性允许我们将各种参数传递给后卫,例如特定角色或检查权限的名称,用户访问该页面所需拥有的积分或积分等.
  • You can attach the CanActivate guard to a top-level route and it will be executed for all of its children routes [TO BE CONFIRMED]. That way you only need to use the guard once. Of course, it only works if the routes to protect are all children of a parent route (that's not the case in Rafael Moura's example).
  • The data property allows us pass all kinds of parameters to the guard, e.g. the name of a specific role or permission to check, a number of points or credits that the user needs to possess to access the page, etc.

考虑到这些注意事项,最好将后卫重命名为更通用的名称,例如AccessGuard.

Taking these remarks into account, it's best to rename the guard to something more generic like AccessGuard.

我只会显示一段代码,在该代码中,警卫人员会检索连接到该路线的data,因为您在警卫人员内部所做的工作实际上取决于您的情况:

I'll only show the piece of code where the guard retrieves the data attached to the route, as what you do inside the guard really depends on your situation:

@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...
    }
  }
}

要执行上述代码,您需要具有类似于以下的路由:

For the above code to be executed, you need to have a route similar to:

{
  path: 'home',
  component: AppComponent,
  data: { requiresLogin: true },
  canActivate: [ AccessGuard ]
}

NB.不要忘记在模块的providers中添加AccessGuard.

NB. Don't forget to add AccessGuard to your module's providers.

这篇关于使用路由器重定向用户,具体取决于登录状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆