我使用Angular 2实现了登录页面。登录后,我从服务器获取jsonwebtoken,userId,userRole,userName。我将此信息存储在localstorage中,以便我可以随时访问它并在用户刷新页面时保持登录状态。
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';
}
}
要检查登录状态,我只是检查localstorage中是否存在令牌。由于localstorage是可编辑的,因此只需在localstorage中添加任何令牌即可绕过登录页面。同样,如果客户端在localstorage中编辑用户角色,客户端可以轻松访问管理员或用户页面。
如何解决这些问题?
这更像是一般问题,我想知道网站如何保持登录状态?
P.S。 NodeJS Server端登录代码生成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));
};
-Thanks
答案 0 :(得分:0)
1)标记应该是唯一的并且难以键入(因为很长)。此外,它们应该以一定的频率刷新。最好在这个
上阅读oAuth docs2)角色不应存储在客户端。只检查服务器。 此外,使用oAuth时请考虑使用Scopes。
答案 1 :(得分:0)
您在服务器端对身份验证令牌进行数字签名:
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
然后,服务器端应在后续请求中验证此签名。当客户端更改令牌的内容时,它将变为无效。
答案 2 :(得分:0)
在localStorage / sessionStorage中存储令牌,并在需要时使用服务器验证令牌。我有以下实现来验证令牌
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);
}
}