如何让 AuthGuard 在 Angular 4 中等待 LocalStorage?
How to make AuthGuard wait for LocalStorage in Angular 4?
我在 Angular 4 和 ASP.Net Core 中开发了一个网站。然而,有一件事一直困扰着我。它有一些基本的 JWT 登录实现,我正在使用本地存储来保存用户对象和令牌。
用户登录后一切正常,但每当我刷新浏览器时 Angular 总是要求我重新登录。我在 AppComponent 上有一个方法可以在每次应用程序启动时刷新令牌和 return 一个新的用户对象(如果它可以重新验证保存在 localStorage 上的令牌,则逻辑发生在 asp net core 中)。
无论如何,我一直在搜索,我相信我需要 return Observables。这是另一个具有非常相似问题的线程:
主要区别在于答案使用 fire base,我相信他们的对象已经是 Observable 而我的是布尔值。
这是我的代码:
存储服务(本地存储)
export class StorageService {
constructor(private storage: LocalStorageService) { }
public user: User = null;
public get isLoggedIn() : boolean {
return this.user != null;
}
public isInRole(roleName: string): boolean {
if (!this.isLoggedIn)
return false;
for (let r of this.user.roles) {
if (r.name == roleName)
return true;
}
return false;
}
public get token(): string {
return <string>this.storage.get(STORAGE_TOKEN) || null;
}
public set token(value: string) {
if (value == null) {
this.storage.remove(STORAGE_TOKEN);
}
else {
this.storage.set(STORAGE_TOKEN, value);
}
}
}
AuthGuard 实施
export class IsLoggedIn implements CanActivate {
constructor(private storage: StorageService, private router: Router) { }
canActivate(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot){
if (this.storage.isLoggedIn) {
return true;
}
this.router.navigate(['account/login'], {
queryParams: {
return: state.url
}
});
return false;
}
}
AppComponent 上的令牌刷新 (ngOnInit)
this.net.get<LoginModel>(`Authentication/RefreshToken`).subscribe(t => {
this.storage.token = t.token;
this.storage.user = t.user;
});
最后,我是这样使用 IsInRole 的:
export class AdminOnly implements CanActivate {
constructor(
private storage: StorageService,
private router: Router
) { }
canActivate(
childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
var message: string = null;
if (!this.storage.isLoggedIn) {
message = 'Você precisa se logar!';
}
if (!this.storage.isInRole('Admin')) {
message = 'Você precisa ser um administrador!';
}
if (message == null) {
return true;
}
this.router.navigate(['account/login'], {
queryParams: {
return: state.url,
message: message
}
});
return false;
}
}
我应该如何将布尔变量转换为 Observables?欢迎就如何解决此问题提出任何其他意见。提前致谢。
您可以将可观察对象上的 .of 用作静态函数。每当您订阅时,它都会引用当前对象状态。
Rx.Observable.of(state)
这是一个代码笔示例:https://codepen.io/ndcunningham/pen/OvVxjx?editors=1111
本地存储服务
public get isLoggedIn() : Observable<boolean> {
return Rx.Observable.of(this.user !== null);
}
后卫
export class IsLoggedIn implements CanActivate {
constructor(private storage: StorageService, private router: Router) { }
canActivate(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.storage.isLoggedIn.do(e => !e && this.router.navigate(['account/login'], {
queryParams: {
return: state.url
}
}));
}
}
我在 Angular 4 和 ASP.Net Core 中开发了一个网站。然而,有一件事一直困扰着我。它有一些基本的 JWT 登录实现,我正在使用本地存储来保存用户对象和令牌。
用户登录后一切正常,但每当我刷新浏览器时 Angular 总是要求我重新登录。我在 AppComponent 上有一个方法可以在每次应用程序启动时刷新令牌和 return 一个新的用户对象(如果它可以重新验证保存在 localStorage 上的令牌,则逻辑发生在 asp net core 中)。
无论如何,我一直在搜索,我相信我需要 return Observables。这是另一个具有非常相似问题的线程:
主要区别在于答案使用 fire base,我相信他们的对象已经是 Observable 而我的是布尔值。
这是我的代码:
存储服务(本地存储)
export class StorageService {
constructor(private storage: LocalStorageService) { }
public user: User = null;
public get isLoggedIn() : boolean {
return this.user != null;
}
public isInRole(roleName: string): boolean {
if (!this.isLoggedIn)
return false;
for (let r of this.user.roles) {
if (r.name == roleName)
return true;
}
return false;
}
public get token(): string {
return <string>this.storage.get(STORAGE_TOKEN) || null;
}
public set token(value: string) {
if (value == null) {
this.storage.remove(STORAGE_TOKEN);
}
else {
this.storage.set(STORAGE_TOKEN, value);
}
}
}
AuthGuard 实施
export class IsLoggedIn implements CanActivate {
constructor(private storage: StorageService, private router: Router) { }
canActivate(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot){
if (this.storage.isLoggedIn) {
return true;
}
this.router.navigate(['account/login'], {
queryParams: {
return: state.url
}
});
return false;
}
}
AppComponent 上的令牌刷新 (ngOnInit)
this.net.get<LoginModel>(`Authentication/RefreshToken`).subscribe(t => {
this.storage.token = t.token;
this.storage.user = t.user;
});
最后,我是这样使用 IsInRole 的:
export class AdminOnly implements CanActivate {
constructor(
private storage: StorageService,
private router: Router
) { }
canActivate(
childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) {
var message: string = null;
if (!this.storage.isLoggedIn) {
message = 'Você precisa se logar!';
}
if (!this.storage.isInRole('Admin')) {
message = 'Você precisa ser um administrador!';
}
if (message == null) {
return true;
}
this.router.navigate(['account/login'], {
queryParams: {
return: state.url,
message: message
}
});
return false;
}
}
我应该如何将布尔变量转换为 Observables?欢迎就如何解决此问题提出任何其他意见。提前致谢。
您可以将可观察对象上的 .of 用作静态函数。每当您订阅时,它都会引用当前对象状态。
Rx.Observable.of(state)
这是一个代码笔示例:https://codepen.io/ndcunningham/pen/OvVxjx?editors=1111
本地存储服务
public get isLoggedIn() : Observable<boolean> {
return Rx.Observable.of(this.user !== null);
}
后卫
export class IsLoggedIn implements CanActivate {
constructor(private storage: StorageService, private router: Router) { }
canActivate(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.storage.isLoggedIn.do(e => !e && this.router.navigate(['account/login'], {
queryParams: {
return: state.url
}
}));
}
}