我是Angular的新手并为用户实施身份验证。
网上的大多数建议都建议将会话/用户名保存在本地存储中,当用户回到应用程序时,检查本地存储以显示正确的导航(在我的导航栏中,我有不同的导航按钮,用于私人和公共视图)。
但是,我发现这种解决方案有一些缺点。例如,如果服务器上的会话已过期,或者手动添加了本地存储,那么当应用程序初始化时,它将在导航栏中显示错误的按钮。
之后我开始解决 - 在显示导航栏按钮之前使用服务,向服务器发送请求以验证来自本地存储的用户当前是否处于活动状态。只有在那之后我才会显示导航按钮。
这里有一个问题:它是验证来自本地存储的用户是否登录并且会话处于活动状态的最有效方法吗?
还有另一种方式,我在考虑,但没有找到解决方案。 由于我的angular webapp和nodejs服务器位于两个不同的位置,因此当请求index.html时,webapp可以检查身份验证状态(从webapp服务器向我的nodejs服务器发出请求)并使用预呈现的导航栏进行响应用户状态(登录与否)?
感谢。
P.S。我在服务器端使用PassportJS和Express。
答案 0 :(得分:0)
最佳做法是使用AuthGuard
并实施CanActivate
来检查用户是否可以查看应用程序的特定部分。此外,通常还使用身份验证服务让用户登录系统并获取访问令牌。
此访问令牌随后在每个服务器请求中用作Authorisation-Header
(这是他们将同步的位置)。
您需要检查加载时的JWT/or any other type
令牌,其中包含用户信息和会话超时。
如果令牌无效,您只需将用户重定向到登录,否则它将允许用户前往他们想要的位置。
可以找到一个实际的例子here。
答案 1 :(得分:0)
要让导航栏显示经过身份验证和未经身份验证的用户的不同元素,可能的解决方案之一将是
authentication.service.ts
中使用某些“/ auth-check”请求,每次检查当前用户授权结果的事件时都会触发...
interface ShareObj { [id: string]: any; }
...
currentUserId: ShareObj = {};
currentUserUsername: ShareObj = {};
public authenticatedBehavior = new ReplaySubject(1);
authCheck(): any {
return this.http.get('/api/auth-check')
.map((resp: any) => {
if (resp.authanticated) {
this.currentUserId['global'] = resp.user.id;
this.currentUserUsername['global'] = resp.user.username;
this.authenticatedBehavior.next(true);
} else {
this.authenticatedBehavior.next(false);
this.currentUserId['global'] = null;
this.currentUserUsername['global'] = null;
}
return resp;
})
.catch(e => {
this.authenticatedBehavior.next(false);
this.currentUserId['global'] = null;
this.currentUserUsername['global'] = null;
});
}
因此,在navbar.component.ts
中应该有一个监听此事件的人:
ngOnInit() {
this.authService.authenticatedBehavior
.subscribe(
data => {
// do change of UI of navbar depending if user logged in or not
}
);
}
error-iterceptor.ts
文件,您应该在其中“捕获”所有失败的请求,并检查它们是否为Unauthorised
响应(401)。如果您收到此类回复,请在authCheck()
中authentication.service.ts
进行操作,以确保当前用户的会话已过期,并通知所有听取authenticatedBehavior
的组件