Angular:AuthGuard 中的浏览器刷新处理
Angular: browser refresh handling in AuthGuard
我一直在尝试在我的网络应用程序中正确实施 AuthGuard。目前,当我在应用程序中导航时,它工作正常。但是当我刷新时,authService.loggedIn 在 AuthService 完成执行之前被处理为 false。
这是我的代码:
auth.guard.ts
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {Injectable} from '@angular/core';
import {AuthService} from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (state.url === '/login') {
if (this.authService.loggedIn) {
this.router.navigate(['/']).then().catch();
} else {
return true;
}
} else {
if (this.authService.loggedIn) {
return true;
} else {
this.router.navigate(['/login']).then().catch();
}
}
}
}
auth.service
import {Injectable, OnInit} from '@angular/core';
import {AngularFireAuth} from '@angular/fire/auth';
import {auth} from 'firebase';
import {Router} from '@angular/router';
import {Subject} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService implements OnInit {
loggedIn = false;
constructor(public afAuth: AngularFireAuth, private router: Router) {
this.afAuth.authState.subscribe((user) => {
if (user) {
this.loggedIn = true;
}
});
}
ngOnInit() {
}
...
}
我在网上研究,他们提到了不同的方法
(例如 https://gist.github.com/codediodeio/3e28887e5d1ab50755a32c1540cfd121)但无法在我的应用程序上运行。
我在尝试这种方法时遇到的一个错误是 "ERROR in src/app/auth.guard.ts(20,8): error TS2339: Property 'take' does not exist on type 'Observable'." 我使用
import {AngularFireAuth} from '@angular/fire/auth';
而不是
import { AngularFireAuth } from 'angularfire2/auth';
感谢任何帮助/建议。
谢谢大家
我能够使 AuthGuard 与浏览器刷新一起工作。
这个link帮助很大:https://gist.github.com/codediodeio/3e28887e5d1ab50755a32c1540cfd121
我只是使用 pipe() 来链接运算符并使用 tap() 而不是 do() 因为我使用的是较新版本的 rxjs。
代码如下:
...
import {Observable} from 'rxjs';
import {take, map, tap} from 'rxjs/operators';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private afAuth: AngularFireAuth) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {
return this.afAuth.authState
.pipe(
take(1),
map(user => !!user),
tap(
loggedIn => {
if (!loggedIn) {
this.router.navigate(['/login']);
}
}
)
);
}
}
谢谢。
您可以按照以下步骤实现:
1) 首先在你的 authService 中,创建一个用户 EX 的 behaviorsubject:
user = new BehaviorSubject<any>(null);
2) 现在在 authService 中创建一个登录函数
logIn(email: string, password: string) {
// do some logging in functionality over here
// like authenticating the user, then emit the userInfo
// and save it to the storage.
this.user.next(userData);
localStorage.setItem('userData', userData);
// also, now here after logging in navigate to your next url which is protected from guard or other some other url.
}
3) 现在创建一个自动登录函数
autoLogin() {
const userData = localStorage.getItem('userData');
if (!userData) {
this.user.next(null);
return;
}
this.user.next(userData);
}
4) 现在在auth.guard.ts中写入如下代码
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service';
import { map, take } from 'rxjs/operators';
@Injectable({providedIn: 'root'})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
this.authService.autoLogin();
return this.authService.user.pipe(take(1), map(user => {
const isAuth = !!user;
if (isAuth) {
return true;
} else {
return this.router.createUrlTree(['/auth']);
}
}));
}
}
5) 不要忘记在你的路由配置中添加 canActivate 对象,你想在其中应用防护
例如
{ path : 'root', component: SuperadminComponent, canActivate: [AuthGuard] }
注意 1 :如果 {providedIn: 'root'} 未在 AuthGuard 的可注入中提供,那么不要忘记将其添加到 [= 的提供程序数组中53=] 或任何你想使用的模块
注 2:注销时清除存储并将用户作为 null 发出。
希望这对您或其他人有所帮助!
我一直在尝试在我的网络应用程序中正确实施 AuthGuard。目前,当我在应用程序中导航时,它工作正常。但是当我刷新时,authService.loggedIn 在 AuthService 完成执行之前被处理为 false。
这是我的代码:
auth.guard.ts
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {Injectable} from '@angular/core';
import {AuthService} from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (state.url === '/login') {
if (this.authService.loggedIn) {
this.router.navigate(['/']).then().catch();
} else {
return true;
}
} else {
if (this.authService.loggedIn) {
return true;
} else {
this.router.navigate(['/login']).then().catch();
}
}
}
}
auth.service
import {Injectable, OnInit} from '@angular/core';
import {AngularFireAuth} from '@angular/fire/auth';
import {auth} from 'firebase';
import {Router} from '@angular/router';
import {Subject} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService implements OnInit {
loggedIn = false;
constructor(public afAuth: AngularFireAuth, private router: Router) {
this.afAuth.authState.subscribe((user) => {
if (user) {
this.loggedIn = true;
}
});
}
ngOnInit() {
}
...
}
我在网上研究,他们提到了不同的方法 (例如 https://gist.github.com/codediodeio/3e28887e5d1ab50755a32c1540cfd121)但无法在我的应用程序上运行。
我在尝试这种方法时遇到的一个错误是 "ERROR in src/app/auth.guard.ts(20,8): error TS2339: Property 'take' does not exist on type 'Observable'." 我使用
import {AngularFireAuth} from '@angular/fire/auth';
而不是
import { AngularFireAuth } from 'angularfire2/auth';
感谢任何帮助/建议。
谢谢大家
我能够使 AuthGuard 与浏览器刷新一起工作。
这个link帮助很大:https://gist.github.com/codediodeio/3e28887e5d1ab50755a32c1540cfd121
我只是使用 pipe() 来链接运算符并使用 tap() 而不是 do() 因为我使用的是较新版本的 rxjs。
代码如下:
...
import {Observable} from 'rxjs';
import {take, map, tap} from 'rxjs/operators';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private afAuth: AngularFireAuth) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {
return this.afAuth.authState
.pipe(
take(1),
map(user => !!user),
tap(
loggedIn => {
if (!loggedIn) {
this.router.navigate(['/login']);
}
}
)
);
}
}
谢谢。
您可以按照以下步骤实现:
1) 首先在你的 authService 中,创建一个用户 EX 的 behaviorsubject:
user = new BehaviorSubject<any>(null);
2) 现在在 authService 中创建一个登录函数
logIn(email: string, password: string) {
// do some logging in functionality over here
// like authenticating the user, then emit the userInfo
// and save it to the storage.
this.user.next(userData);
localStorage.setItem('userData', userData);
// also, now here after logging in navigate to your next url which is protected from guard or other some other url.
}
3) 现在创建一个自动登录函数
autoLogin() {
const userData = localStorage.getItem('userData');
if (!userData) {
this.user.next(null);
return;
}
this.user.next(userData);
}
4) 现在在auth.guard.ts中写入如下代码
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, Router } from '@angular/router';
import { AuthService } from './auth.service';
import { map, take } from 'rxjs/operators';
@Injectable({providedIn: 'root'})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
this.authService.autoLogin();
return this.authService.user.pipe(take(1), map(user => {
const isAuth = !!user;
if (isAuth) {
return true;
} else {
return this.router.createUrlTree(['/auth']);
}
}));
}
}
5) 不要忘记在你的路由配置中添加 canActivate 对象,你想在其中应用防护
例如
{ path : 'root', component: SuperadminComponent, canActivate: [AuthGuard] }
注意 1 :如果 {providedIn: 'root'} 未在 AuthGuard 的可注入中提供,那么不要忘记将其添加到 [= 的提供程序数组中53=] 或任何你想使用的模块
注 2:注销时清除存储并将用户作为 null 发出。
希望这对您或其他人有所帮助!