【发布时间】:2022-10-24 14:32:02
【问题描述】:
我正在尝试使用警卫,但我无法让他们工作。
我想要CheckAuthGuard,它将检查localStorage中的令牌; AuthGuard,它将检查用户是否已登录,RolesAuthGuard 将检查用户是否具有所需的角色。
我之前问过问题:“如何检查 localStorage 中的用户令牌”。我试图在onInit 中创建检查功能,但一个人告诉我,我需要使用早先加载的保护onInit。(这需要直接进入管理页面,而不是从主页)
起初一切都解决了,但后来我破坏了代码。我希望你能告诉我如何正确地做到这一点。
这是我使用的代码
auth.guard.ts
import {ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router, RouterStateSnapshot} from "@angular/router";
import {Observable, of} from "rxjs";
import {Injectable} from "@angular/core";
import {AuthService} from "../servicies/auth.service";
import {ToastService} from "../servicies/toast.service";
@Injectable({
providedIn:'root'
})
export class CheckAuthGuard implements CanActivate, CanActivateChild {
constructor(private auth:AuthService, private router:Router) {
}
canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
if (this.auth.isAuth){
return of(true)
} else {
if (localStorage.getItem('token')) {
this.auth.checkAuth().subscribe(
(data) => {
console.log(data)
console.log(this.auth.isAuth)
console.log(`Check auth ${this.auth.isAuth}`)
}
)
return of(true)
}
else{
return of(true)
}
}
}
canActivateChild(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
return this.canActivate(route, state)
}
}
@Injectable({
providedIn:'root'
})
export class AuthGuard implements CanActivate, CanActivateChild {
constructor(private auth:AuthService, private router:Router) {
}
canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
if (this.auth.isLoggedIn()){
return of(true)
} else {
this.router.navigate(['/login'])
return of(false)
}
}
canActivateChild(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
return this.canActivate(route, state)
}
}
@Injectable({
providedIn:"root"
})
export class AuthRolesGuard implements CanActivate, CanActivateChild {
constructor(private auth:AuthService, private router:Router, private toast: ToastService) {
}
canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
if (this.auth.isAuth){
let userRoles = route.data['roles'] || [] as number[]
if (this.auth.user.roles.find( role=> userRoles.includes(role))){
return of(true)
} else {
this.router.navigate(['/'])
this.toast.show({textOrTpl:'You dont have access to this!!', options:{classname:'bg-danger text-light alert', delay:10000}})
return of(false)
}
} else {
this.router.navigate(['/login'])
return of(false)
}
}
canActivateChild(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean>{
return this.canActivate(route, state)
}
}
app-routing.module.ts
import {NgModule} from "@angular/core";
import {RouterModule, Routes} from "@angular/router";
import {AuthLayoutComponent} from "./shared/layouts/auth-layout/auth-layout.component";
import {SiteLayoutComponent} from "./shared/layouts/site-layout/site-layout.component";
import {LoginPageComponent} from "./login-page/login-page.component";
import {RegistrationPageComponent} from "./registration-page/registration-page.component";
import {ProfilePageComponent} from "./profile-page/profile-page.component";
import {AuthGuard, AuthRolesGuard, CheckAuthGuard} from "./shared/classes/auth.guard";
import {MainPageComponent} from "./main-page/main-page.component";
const routes: Routes = [
{
path:'', component: AuthLayoutComponent, canActivateChild:[CheckAuthGuard], children: [
{path:'', component: MainPageComponent},
{path:'login', component:LoginPageComponent},
{path:'registration', component:RegistrationPageComponent},
{path: 'profile', component: ProfilePageComponent, canActivate: [AuthGuard]}
]
},
{
path:'admin', component: SiteLayoutComponent,canActivate:[AuthGuard],data:{roles:[10]}, children: [
]
}
]
@NgModule({
imports:[
RouterModule.forRoot(routes)
],
exports : [
RouterModule
]
})
export class AppRoutingModule{
}
auth.service.ts
import {Injectable} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {Observable} from "rxjs";
import {IUser, UserDto} from "../interfaces";
import {tap} from 'rxjs/operators'
@Injectable({
providedIn:'root'
})
export class AuthService{
constructor(private http:HttpClient) {
}
user = {} as IUser
isAuth:boolean = false
isLoading:boolean = false
register(email:string, password:string, username:string): Observable<UserDto>{
return this.http.post<UserDto>('/api/user/registration', {email, password, username})
.pipe(
tap(
({accessToken, user}) => {
localStorage.setItem('token', accessToken)
this.setAuth(true)
this.setUser(user)
}
)
)
}
login(email:string, password:string): Observable<UserDto>{
return this.http.post<UserDto>('/api/user/login', {email, password})
.pipe(
tap(
({accessToken, user}) => {
localStorage.setItem('token', accessToken)
this.setAuth(true)
this.setUser(user)
}
)
)
}
isLoggedIn(){
return this.isAuth
}
setAuth(bool:boolean){
this.isAuth = bool
}
setUser(user:IUser){
this.user = user
}
setLoading(bool:boolean){
this.isLoading = bool
}
logout(): Observable<void> {
console.log('logout')
this.setAuth(false)
this.setUser({} as IUser)
localStorage.removeItem('token')
return this.http.post<void>('/api/user/logout', {})
}
checkAuth():Observable<UserDto>{
return this.http.get<UserDto>(`/api/user/refresh`, {withCredentials:true, observe:'body', responseType:'json'})
.pipe(
tap(
(data) => {
localStorage.setItem('token', data.accessToken)
this.setAuth(true)
this.setUser(data.user)
},
(error) => {
console.log(error)
}
)
)
}
}
【问题讨论】:
-
你究竟是如何“破解”代码的?它的表现如何,您期望它的表现如何?
-
@AllanJuan 嗨,我想直接访问
/admin并查看管理页面(我的帐户具有 id 10 的角色),但现在如果我直接访问/admin或从主页访问我会看到登录页面,这意味着我没有记录身份证。我在 localStorage 中有我的令牌,所以应该可以。例如,如果我想访问/profile页面,我也会看到登录页面,但我有令牌。如果我从主页转到个人资料页面,我可以看到它。 -
例如,在我的
app-routing.module.ts中,在个人资料页面中,AuthGuard 在 CheckAuthGuard 之前工作,我不知道如何解决这个问题。 -
我认为问题出在 CheckAuthGuard 中,它发出请求,然后 AuthGuard 开始工作,无需等待 CheckAuthGurd
标签: angular typescript angular-router-guards