gpt4 book ai didi

Angular Universal - Auth Guard 未决问题

转载 作者:行者123 更新时间:2023-12-05 02:46:39 25 4
gpt4 key购买 nike

我在 Angular Material 中使用弹出登录,当我添加 Angular Universal 时,auth guard 是问题所在。如果某些路由受 auth guard 保护,则该页面只会开始挂起并且永远不会完成。没有 Angular Universal 的行为是在页面重新加载时它只是打开弹出窗口进行登录。

@Injectable()
export class AuthGuard implements CanActivate {
constructor(readonly auth: AuthService, public router: Router, private dialog: MatDialog, private store: Store<fromAuth.State>) {}

/** Performs the user authentication prompting the user when neeed or resolving to the current authenticated user otherwise */

public authenticate(action: loginAction = 'signIn') {
return this.store.pipe(
select(fromAuth.selectAuthState),
take(1),
switchMap(user => !user.user ? this.prompt(action) : of(user.user))
).toPromise();
}

public prompt(data: loginAction = 'signIn'): Promise<any> {

return this.dialog.open<LogInComponent, loginAction>(LogInComponent, { data }).afterClosed().toPromise();
}

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
// Gets the authorization mode when specified
// const mode = route.queryParamMap.get('authMode') || 'signIn';
// Prompts the user for authentication
return this.authenticate()
.then(user => !!user);
}
}

如果我直接访问 canActivate 中的 ngrx 商店它正在工作,但我想使用 .toPromise()

我正在使用 httponly cookies,每次重新加载时,Angular 都会向 nodejs 数据库发送 http 请求以获取用户数据。在所有其他路线上它都按预期工作。

最佳答案

目前没有太多时间,但有一些想法:

  1. 如果您在服务器端呈现 Angular 页面 (Angular Universal),为什么不在服务器端处理身份验证过程?检查用户是否在每个请求中登录并在登录页面上重定向用户 - 您将需要一个独立的登录页面而不是覆盖。

  2. 我有多个使用 AuthGuard/User/Auth 运行的项目,我不建议返回 promise,而是返回 canActivate 的 bool 值。

因为:

  • 实际上您不需要检查每个请求的登录状态,因为您的 session 通常在一段时间内有效。
  • 我通常会在登录过程完成后存储有关用户的副本或一些紧凑的信息。
  • 每个例如。 1 分钟后调用某个身份验证端点“whoami”或“loggedin”,返回用户 session 是否仍然有效。
  • 如果不是,则用户已注销。
  • 如果您想在浏览器或标签页关闭时保持 session 事件,您可以将用户对象存储在本地存储中一段时间​​。

-> 这样你只能检查你的 canActivate 方法中是否设置了当前用户对象并返回 true 或 false。

所以在我看来:要么完全使用服务器端渲染,这意味着还要在后端检查用户的身份验证状态。或者将 Angular 用作真正的前端项目并在那里处理身份验证过程。混合这两个世界会导致一些棘手的问题,并使维护变得不必要的复杂。

示例路由

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthGuardService, CanDeactivateGuard } from '@app/core/services';
import { AppPagesConfig } from '@app/config';
import * as Pages from '@app/pages';

const routes: Routes = [
{
path: 'dashboard',
component: Pages.DashboardPage,
canActivate: [AuthGuardService],
data: {
permissions: []
}
}, {
path: 'calendar',
children: [
{
path: '',
redirectTo: AppPagesConfig.calendarPersonal.path,
pathMatch: 'full'
}, {
path: AppPagesConfig.calendarPersonal.path,
component: Pages.CalendarPersonalPage,
canActivate: [AuthGuardService],
data: {
permissions: 'Foo-canEdit'
}
}, {
path: AppPagesConfig.calendarTeam.path,
component: Pages.CalendarTeamPage,
canActivate: [AuthGuardService],
data: {
permissions: '0100'
}
},
]
}, {
path: 'contacts',
children: [
{
path: '',
redirectTo: 'private',
pathMatch: 'full'
}, {
path: 'private',
component: Pages.ContactsPage,
canActivate: [AuthGuardService],
canDeactivate: [CanDeactivateGuard],
data: {
permissions: []
}
},
]
}, {
path: 'errors',
children: [
{
path: '',
redirectTo: '404',
pathMatch: 'full'
}, {
path: '404',
component: Pages.ErrorNotFoundPage
}, {
path: '403',
component: Pages.ErrorNoPermissionsPage
},
]
}, {
path: 'login',
component: Pages.LoginPage
}, {
path: '**',
component: Pages.ErrorNotFoundPage
}
];

@NgModule({
imports: [
RouterModule.forRoot(routes, {
useHash: true
})
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }

示例用户模型

import { uniq, union } from 'lodash';
import { UserBaseModel } from '@app/models/user-base';
import { Deserializable } from './deserializable.model';

export class User implements Deserializable {
public permissions: string[];

/**
* Call this function to fill the model with data.
*/
public deserialize(input: UserBaseModel): this {
Object.assign(this, input);
this.updateUserPermissions();

return this;
}

/**
* Checks if the user has all required permissions.
*/
public hasPermissions(requiredPermissions: string[]): boolean {
// If there where no required permissions given it is valid.
if (!requiredPermissions || !requiredPermissions.length) {
return true;
}

// If there are required permissions given but the user has no permissions at all it is always invalid.
if (requiredPermissions.length && !this.permissions.length) {
return false;
}

// Check the users permissions to contain all required permissions.
for (const permission of requiredPermissions) {
if (!this.permissions.includes(permission)) {
return false;
}

}

return true;
}
}

AuthGuard 示例

import { isEmpty } from 'lodash';
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { SessionService } from './session.service';

@Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
constructor(
private readonly _router: Router,
private readonly sessionService: SessionService
) { }

/**
* Check if user is allowed to navigate to the new state.
*/
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
const currentUser = this.sessionService.getCurrentUser();

// Not logged in so redirect to login page.
if (!currentUser) {
this.sessionService.logoutUser();
this._router.navigate(['/login']);

return false;
}

// Route is not protected so continue (for routes without auth permission needed).
if (isEmpty(route.data) || !route.data.permissions || !route.data.permissions.length) {
return true;
}

// If the permissions do not match redirect.
if (currentUser && !currentUser.hasPermissions(route.data.permissions)) {
this._router.navigate(['/errors/403'], {
queryParams: {
referrerUrl: state.url
}
});

return false;
}

// If the permissions do match continue.
if (currentUser && currentUser.hasPermissions(route.data.permissions)) {
return true;
}

// If nothing matches log out the user.
this.sessionService.logoutUser();
this._router.navigate(['/login']);

return false;
}
}

关于Angular Universal - Auth Guard 未决问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65389193/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com