【问题标题】:Errors while implementing Angular 8 Route (Auth) Guards实施 Angular 8 Route (Auth) Guards 时出错
【发布时间】:2019-11-18 10:11:20
【问题描述】:

所以我试图为我的 web 应用程序实现 Route Guards,但遇到了很多错误。我做错了什么?

我的 webapp 由多个路由组成,其中一个是仪表板,需要通过登录组件进行保护。这正是我尝试实施但失败的方法。我的登录组件从后端生成一个 JWT 令牌并将其添加到 LocalStorage 中(以对象“令牌”的格式:“”)。

我的dashboard.component.ts:

import { Component, OnInit } from '@angular/core';
import { User } from '../models/user.model';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
  user: User;

  constructor() { }

  ngOnInit() {
  }

  canDeactivate(): Promise<any> | boolean {
    if (localStorage.getItem('currentUserToken') === 'token') {
            return (true);
          } else {
            return (false);
          }

}
}

我的 auth.guard.ts:

import {Injectable} from '@angular/core';
import {ActivatedRoute, ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot} from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate, CanLoad {
    constructor(private router: Router) {
    }
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return this.checkToken();
    }
    canLoad(route: Route): boolean {
        return this.checkToken();
    }
    checkToken() {
        if (localStorage.getItem('currentUserToken')) {
            return true;
        } else {
            this.router.navigateByUrl('/avior/login');
            return false;
        }
    }
}

我的 can-exit.guard.ts:

import {Injectable} from '@angular/core';
import {CanDeactivate} from '@angular/router';
import {CanExit} from './canExit';
@Injectable()
export class CanExitGuard implements CanDeactivate<CanExit> {
 canDeactivate(component: CanExit) {
   if (component.canDeactivate) {
     return component.canDeactivate();
   }
   return true;
 }
}

我的 canExit.ts:

import {Observable} from 'rxjs';
export interface CanExit {
 canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

浏览器中的错误是:

DashboardComponent.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'id' of undefined
DashboardComponent.ngfactory.js? [sm]:1 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 1, nodeDef: {…}, elDef: {…}, elView: {…}}
ERROR TypeError: Cannot read property 'id' of undefined
ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 1, nodeDef: {…}, elDef: {…}, elView: {…}}

更新: StackBlitz: https://stackblitz.com/edit/angular-v9u7nw?file=src%2Fapp%2Fapp.routing.ts

【问题讨论】:

  • 这里有什么问题。首先你只想要登录页面,然后只有登录成功后才想要仪表板页面?
  • @GaurangDhorda 需要通过检查 LocalStorage 中的令牌是否存在来保护仪表板,如果存在则允许访问,否则拒绝它
  • 忠告 - 永远不要将 JWT 存储在本地存储中。任何其他网站都可以轻松阅读它们。
  • @batbrain9392 这只是一个原型,将来它应该使用安全的 HttpOnly cookie。附带说明:您如何阅读 localStorage 跨站点?因为这也是我遇到的问题(我的后端应该清除我的前端本地存储)
  • 您能在 stackblitz 中复制这个问题吗?因为对我来说,似乎“无法读取 id”问题可能与您的路线守卫无关。更多关于本地存储问题:dev.to/rdegges/please-stop-using-local-storage-1i04

标签: angular authentication authorization angular8 angular-route-guards


【解决方案1】:

为了将用户重定向到登录组件,您需要在路由路径中定义路由器保护。我在这里不是为这个用例设置令牌部分。你可以找到完整的工作StackBlitz Link here。如果你直接重定向到/dashboard,如果用户没有登录,auth-guard 会重定向到/login。

你的 auth-guard 是..

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean> | Promise<boolean> | boolean {

   if(this.authService.isUserLoggedIn()){
       return true;
   }else{
      this.router.navigate(['/login'],{relativeTo: this.activatedRouter});
        return false;
    }
}

您的身份验证服务如下所示..

 isAuthenticated(username: string, password: string): Observable <boolean>{
return this.getAllUsers().pipe(
  map(users => {
    let user = users.find( user => (user.username === username) && (user.password === password) );
        console.log(user)
        if (user) {
          this.isLoggedin = true;
          this.loggedInUser = user;
        } else {
          this.isLoggedin = false;
        }
        return this.isLoggedin;
  })
)
}

您的应用路由模块是..

const routes: Routes = [{path: 'login', component: LoginComponent},
                    {path: '', redirectTo: 'login',  pathMatch: 'full'},
                    {path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard]}
                    ];

您的登录提交方法..

this.authService.isAuthenticated(this.loginForm.get('username').value,this.loginForm.get('password').value).subscribe(authenticated =>{
    if (authenticated){
      let url = this.authService.getRedirectUrl();
       this.router.navigate([url]);
    }
});

【讨论】:

  • 嗯,您的代码似乎给了我错误,例如“AuthenticationService”类型上不存在属性“isLoggedin”,“未知”类型上不存在属性“查找”。等
  • 你检查过 StackBlitz 链接吗?
  • 我在本地克隆了您发送给我的 StackBlitz 链接,我将其用作构建自己的应用程序的参考。
  • 你改变了什么?
  • 我尝试复制粘贴您在答案中提供的代码 sn-ps,现在我正在尝试查看您的 StackBlitz 项目,该项目似乎更完整(满足我的需要)本地存储副本的版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-21
  • 2016-11-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2018-06-07
  • 2018-12-12
相关资源
最近更新 更多