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

时间:2017-01-29 15:19:40

标签: angular typescript login routes router

我想通过角度2

中的路径调用页面

在我的app.modules中,我使用了RouterModule和Routes,看起来很好看:

...

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]
})

我最初有两个页面,仪表板和登录,我想加载第一个登录页面和afeter仪表板页面,如果有其他条件......

在主页面“appcomponent.ts”中,如何进行此操作是条件登录和仪表板前

if(loggedin){
  // page dashboard
}else{
   // page login
}

2 个答案:

答案 0 :(得分:64)

以下是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

然后我需要实现它。在这个例子中,我将使用guard来重定向用户,如果他们没有登录:

@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警卫。

太糟糕了,你说。现在我需要为每个受保护的路由添加两个东西:元数据和守卫......

BUT:

  • 您可以将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 ]
}

NB。不要忘记将AccessGuard添加到模块的providers

答案 1 :(得分:0)

您还可以执行以下操作:

{
  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;
  }
}