Angular 6:刷新后从localStorage获取令牌
Posted
技术标签:
【中文标题】Angular 6:刷新后从localStorage获取令牌【英文标题】:Angular 6: Get Token from localStorage After Refresh 【发布时间】:2019-04-16 08:50:22 【问题描述】:编辑:我用 PierreDuc 给我的答案更新了代码。他的解决方案对我有用。我编辑了代码,这样每个人都可以看到工作代码
我正在使用 canActivate 和 canActivateChild 来了解是否有人拥有我的网站的令牌,我想阻止任何没有令牌的人。 我将 localStorage 用于用户数据和令牌。
当我尝试使用用户 id:1 登录时,守卫导航到未找到的页面,但在我刷新页面后,我可以访问该页面。 当我使用调试器时,我看到在刷新之前 localStorage 是空的,但在刷新之后有值。
为什么会这样?我该如何解决? 这是相关代码:
app-routing.module.ts
const appRoutes: Routes = [
path: 'login/:id', canActivate: [AuthGuard], children: [] ,
path: '', canActivateChild: [AuthGuard], children: [
path: '', redirectTo: '/courses', pathMatch: 'full' ,
path: 'courses', component: CourseListComponent, pathMatch: 'full',
path: 'courses/:courseId', component: CourseDetailComponent, pathMatch: 'full' ,
path: 'courses/:courseId/unit/:unitId', component: CoursePlayComponent,
children: [
path: '', component: CourseListComponent ,
path: 'lesson/:lessonId', component: CourseLessonComponent, data: type: 'lesson' ,
path: 'quiz/:quizId', component: CourseQuizComponent, data: type: 'quiz'
]
],
path: '**', component: PageNotFoundComponent, pathMatch: 'full' ];
auth.guard.ts
export class AuthGuard implements CanActivate , CanActivateChild
constructor(private authUserService: AuthUserService, private router: Router)
canActivate(route: ActivatedRouteSnapshot, state:
RouterStateSnapshot): boolean |
Observable<boolean> | Promise<boolean>
// save the id from route snapshot
const id = +route.params.id;
// if you try to logging with id
if (id)
this.router.navigate(["/courses"]);
return this.authUserService.login(id);
// if you already logged and just navigate between pages
else if (this.authUserService.isLoggedIn())
return true;
else
this.router.navigate(["/page_not_found"]);
return false;
canActivateChild(route: ActivatedRouteSnapshot,state: RouterStateSnapshot): boolean |
Observable<boolean> | Promise<boolean>
return this.canActivate(route, state);
auth-user.service.ts
import Injectable, OnDestroy from '@angular/core';
import Observable , BehaviorSubject from 'rxjs';
import LocalStorage from '@ngx-pwa/local-storage';
import of from 'rxjs';
import map from 'rxjs/operators';
import catchError, groupBy from 'rxjs/operators';
import UserService from './user.service';
import IUser from './user';
@Injectable()
export class AuthUserService implements OnDestroy
private user: IUser;
private errorMessage: string;
constructor(private userService: UserService)
// store the session and call http get
login(id: number)
return this.userService.getUser(id).pipe(
map((user) =>
this.user = user;
localStorage.setItem('user', JSON.stringify(this.user));
localStorage.setItem('token', 'JWT');
return true;
),
catchError((error) =>
this.errorMessage = <any>error;
return of(false);
)
);
isLoggedIn()
return !!localStorage.getItem('token');
ngOnDestroy()
localStorage.removeItem('user');
localStorage.removeItem('token');
【问题讨论】:
【参考方案1】:userService.getUser
是异步的,它不会完成,并且会在您检查后设置您的 localStorage。
将您的 authService 更改为:
login(id: number)
return this.userService.getUser(id).pipe(
map((user) =>
this.user = user;
localStorage.setItem('user', JSON.stringify(this.user));
localStorage.setItem('token', 'JWT');
return true;
),
catchError((error) =>
this.errorMessage = <any>error;
return of(false);
)
);
然后更新你的警卫:
if (id)
this.router.navigate(["/courses"]);
return this.authUserService.login(id);
【讨论】:
我按照你说的做了,现在当我尝试访问 localhost:4200/login/1 => ERROR 错误:未捕获(承诺):ReferenceError:未定义 of 是来自 rxjs 的运算符,您必须使用import of from 'rxjs';
导入它,catchError
和 map
相同。 CatchError 必须返回一个 observable
map 更新 observable 发出的值。订阅触发冷可观察..这不是你想要的,但只有在角度检查守卫时
是的..你必须从rxjs/operators
导入它
啊,是的,我看错了你的路线。您也对 login/:id 路径使用相同的保护。您确实必须添加重定向。对于那个很抱歉。我会更新我的答案以上是关于Angular 6:刷新后从localStorage获取令牌的主要内容,如果未能解决你的问题,请参考以下文章
除非我刷新页面,否则 Javascript localStorage 在其他组件中不可用