Angular 2authentication状态

我已经使用Angular 2实现了一个login页面。login后,我从服务器获取了jsonwebtoken,userId,userRole,userName。 我将这些信息存储在localstorage中,以便我可以随时访问它,并在用户刷新页面时保持login状态。

AuthService.ts

import {Injectable} from "@angular/core"; @Injectable() export class AuthService { redirectUrl: string; logout() { localStorage.clear(); } isLoggedIn() { return localStorage.getItem('token') !== null; } isAdmin() { return localStorage.getItem('role') === 'admin'; } isUser() { return localStorage.getItem('role') === 'user'; } } 

要检查login状态,我只是检查是否存在本地存储令牌。 由于localstorage是可编辑的,因此在localstorage中添加任何标记都会绕过login页面。 同样,如果客户端在本地存储中编辑用户angular色,则客户端可以轻松访问pipe理员或用户页面。

我如何解决这些问题?

这更像是一个普遍的问题,我想知道网站如何保持login状态?

PS NodeJS服务器端login代码来生成jsonwebtoken

 const jwt = require('jsonwebtoken'); const User = require('../models/User'); /** * POST /login * Sign in using username and password */ exports.postLogin = (req, res, next) => { User.findOne({username: req.body.username}) .then(user=> { if (!user) { res.status(401); throw new Error('Invalid username'); } return user.comparePassword(req.body.password) .then(isMatch=> { if (isMatch != true) { res.status(401); throw new Error('Invalid password'); } let token = jwt.sign({user: user}, process.env.JWT_SECRET, { expiresIn: process.env.JWT_TIMEOUT }); return res.status(200).json({ success: true, token: token, userId: user._id, role:user.role, name:user.name }); }); }) .catch(err=>next(err)); }; 

-谢谢

1)令牌应该是独一无二的,难以打字(长度很大)。 而且,他们应该刷新一些频率。 最好阅读oAuth文档

2)angular色不应该存储在客户端。 只检查服务器。 此外,使用oAuth时考虑使用范围。

您在服务器端数字签名身份validation令牌:

 jwt.sign({user: user}, process.env.JWT_SECRET, { expiresIn: process.env.JWT_TIMEOUT }) 

然后这个签名应该由服务器端在随后的请求中validation。 当客户端更改令牌的内容时,它将变为无效。

将令牌存储在localStorage / sessionStorage中,并在需要时使用服务器validation令牌。 我正在执行以下validation令牌

UserProfileService.ts

 @Injectable() export class UserProfileService { private isLoggedIn: boolean = false; private apiEndPoint: string; constructor(private http: Http) { this.apiEndPoint = environment.apiEndpoint; } login(token: string) { localStorage.setItem('auth_token', token); this.isLoggedIn = true; } logout(){ localStorage.removeItem('auth_token'); this.isLoggedIn = false; } isAuthorized(): Observable<boolean> { if (!this.isLoggedIn) { let authToken = localStorage.getItem('auth_token'); if(authToken){ let headers = new Headers(); headers.append('Content-Type', 'application/json'); headers.append('Accept', 'application/json'); headers.append('Authorization', `Bearer ${authToken}`); return this.http.get(`${this.apiEndPoint}/validate-token`, { headers: headers }) .map(res => { let serverResponse = res.json(); this.isLoggedIn = serverResponse['valid']; if (!this.isLoggedIn) { localStorage.removeItem('auth_token'); } return this.isLoggedIn; }) .catch(this._serverError); } } return Observable.of(this.isLoggedIn); } private _serverError(err: any) { localStorage.removeItem('auth_token'); if(err instanceof Response) { console.log(err.json()); return Observable.of(false); } return Observable.of(false); } } 

AuthService.ts

 @Injectable() export class CanActivateAuthGuard implements CanActivate, CanActivateChild, CanLoad { constructor(private userProfileService: UserProfileService, private router: Router) { } canLoad(route: Route) { return this.userProfileService.isAuthorized().map(authorized => { if(authorized) { return authorized; } else { let url = `/${route.path}`; this.router.navigate(['/login'], { queryParams: { redirectTo: url } }); return authorized; } }); } canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ) { return this.userProfileService.isAuthorized().map(authorized => { if(authorized) { return authorized; } else { this.router.navigate(['/login'], { queryParams: { redirectTo: state.url } }); return authorized; } }); } canActivateChild( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ) { return this.canActivate(route, state); } }