1.每次登录,用refresh_token,更新该用户名的token
保证最近一次所登录用户的token最新
login() {
let fontSize = localStorage.getItem("fontSize")
this.userServ.login(this.username, this.password).toPromise().then(() => {
this.userServ.updateToken().subscribe(token => {
this.userServ.getRolesByUsername(this.username).subscribe(info => {
if (info.length == 0) {
this.message.error("系统不存在此用户名!");
return
}
if (info[0].name.match("ROLE_CEMSS")) {
this.http.get('assets/sysconfig/sysconfig.json').subscribe((data: SysConfig) => {
this.userServ.getUserInfo(this.username).toPromise().then(userinfo => {
this.message.loading("登录成功,正在跳转...")
localStorage.setItem("fontSize", fontSize ? fontSize : data.font_size);
this.areaServ.getByKey(userinfo.areaCode).then(area => {
if (area.cCode == 100000) {
this.apiServ.title = "国家级生态气象业务云平台"
} else {
this.apiServ.title = `${area.cName}生态气象业务云系统`;
}
this.apiServ.areaCode = userinfo.areaCode;
this.message.remove();
this.message.success("登录成功");
this.refreshLoginStatus();
this.getPowerMenu();
})
})
})
} else {
this.message.error("系统不存在此用户名!");
}
}, e => {
this.message.error("系统验证用户失败!");
})
}, (err) => {
this.message.error("更新Token失败:" + JSON.stringify(err));
})
}).catch((err) => {
this.message.error("登录失败:" + JSON.stringify(err));
this.refreshLoginStatus();
});
}
2.设置定时器,定时检验token
登录时,保存token、refresh_token到sessionStorage.
let interval = setInterval(() => {
if (this.apiServ.token == null) {
clearInterval(interval);
this.router.navigate(['/welcome']);
} else {
this.userServ.checkToken().subscribe(data => { }, (error) => {
clearInterval(interval);
this.modalService.closeAll();
this.message.error('登录失效!!!')
this.apiServ.clearToken();
this.router.navigate(['/welcome']);
})
}
}, 60000)
3.若token失效,取消定时器、退出登录
user.service.ts
import { Injectable } from '@angular/core';
import { ApiService } from './api.service';
import { HttpClient, HttpParams } from '@angular/common/http';
import { AppConfig } from './app.config';
import { Token } from '../model/token';
import { Observable } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { CacheService } from './cache.service';
import { ErrorHandler } from '../model/error-handler';
@Injectable()
export class UserService extends ApiService {
private url: string;
private pwd: string;
constructor(http: HttpClient, private appConfig: AppConfig, private cacheService: CacheService, private errorHandler: ErrorHandler) {
super(http);
this.url = this.appConfig.sysConfig.user_url;
}
public login(username: string, password: string): Observable<Token> {
let url = this.url + '/oauth/token?grant_type=password&username=' + username + '&password=' + password;
let options = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + 'eXotc2VydmljZS1jbGllbnQ6YWdtczEyMzQ='
}
};
return this.http.post<Token>(url, null, options).pipe(map((token: Token) => {
this.setToken(token, username);
sessionStorage.setItem("token", token.access_token);
this.cacheService.cache();
return token;
}));
}
public updateToken(): Observable<Token> {
let url = this.url + '/oauth/token?grant_type=refresh_token&refresh_token=' + this.refresh_token;
let options = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + 'eXotc2VydmljZS1jbGllbnQ6YWdtczEyMzQ='
}
};
return this.http.post<Token>(url, null, options).pipe(map((token: Token) => {
sessionStorage.setItem("token", token.access_token);
this.cacheService.cache();
return token
}));
}
public checkToken() {
let url = this.url + '/oauth/check_token?token=' + this.token;
let options = { headers: super.jwt() };
return this.http.get<any>(url, options).pipe(map((data) => {
return data
})).pipe(catchError(this.errorHandler.handleError));
}
public getUserInfo(username: string) {
let url = this.url + '/oauth/users/info';
let params: HttpParams = new HttpParams()
params = params.set('username', username);
let options = { headers: super.jwt(), params: params };
return this.http.get<any>(url, options).pipe(map(userinfo => userinfo));
}
public getUserMenu(systemName: string, userName: string): Observable<Array<PowerMenu>> {
let url = this.url + '/oauth/users/user/menus';
let params: HttpParams = new HttpParams()
params = params.set('systemName', systemName);
params = params.set('userName', userName);
let options = { headers: super.jwt(), params: params };
return this.http.get<Array<PowerMenu>>(url, options).pipe(map((powerMenu: Array<PowerMenu>) => powerMenu));
}
getRolesByUsername(username: string) {
let url = this.url + '/oauth/roles/username/' + username;
return this.http.get(url, { headers: super.jwt() })
.pipe(map((nameInfo: Array<any>) => {
return nameInfo;
}))
}
}
export class PowerMenu {
id: number;
systemId: number;
leaf: boolean;
parentId: number;
name: string;
cname: string;
children: Array<PowerMenu>;
permissions: {
id: number;
name: string;
permissionUrl: string;
method: string,
description: string
}[];
}
api.service.ts
import { Injectable, APP_INITIALIZER } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { AppConfig, SysConfig } from './app.config';
import { Token } from '../model/token';
@Injectable({ providedIn: 'root' })
export class ApiService {
public set areaCode(areaCode: number) {
sessionStorage.setItem("areaCode", areaCode.toString());
}
public get areaCode(): number {
return Number(sessionStorage.getItem("areaCode"));
}
public setToken(token: Token, username: string) {
sessionStorage.setItem("token", token.access_token);
sessionStorage.setItem("login_time", new Date().getTime().toString());
sessionStorage.setItem("expires_in", token.expires_in.toString());
sessionStorage.setItem("username", username);
sessionStorage.setItem("refresh_token", token.refresh_token);
}
public get refresh_token(): string {
return sessionStorage.getItem("refresh_token");
}
public get token(): string {
return sessionStorage.getItem("token");
}
private get expires_in(): number {
return Number(sessionStorage.getItem("expires_in"));
}
private get login_time(): string {
return sessionStorage.getItem("login_time");
}
public get username(): string {
return sessionStorage.getItem("username");
}
public clearToken(): void {
sessionStorage.removeItem("token");
sessionStorage.removeItem("login_time");
sessionStorage.removeItem("expires_in");
sessionStorage.removeItem("username");
sessionStorage.removeItem("areaCode");
sessionStorage.removeItem("refresh_token");
}
public set title(title: string) {
sessionStorage.setItem("title", title);
}
public get title(): string {
return sessionStorage.getItem("title");
}
public get isTokenExpires(): boolean {
let time = new Date().getTime() - Number(this.login_time);
return time > (this.expires_in - 10) * 1000;
}
constructor(protected http: HttpClient) {
}
public getWebUrl() {
let host = window.location.hostname || '127.0.0.1';
let port = window.location.port || 81;
return 'http://' + host + ':' + port;
}
public jwt(): HttpHeaders {
if (this.token) {
return new HttpHeaders().set("Authorization", 'Bearer ' + this.token);
}
return null;
}
}
app.config.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
const jsonFile = 'assets/sysconfig/sysconfig.json';
@Injectable()
export class AppConfig {
private _sysConfig: SysConfig;
constructor(private http: HttpClient) { }
load() {
return new Promise<void>((resolve, reject) => {
this.http.get(jsonFile).toPromise().then((data: SysConfig) => {
this._sysConfig = data;
resolve();
}).catch((response: any) => {
reject(`load sysConfig file '${jsonFile}' error`);
});
});
}
get sysConfig(): SysConfig {
return this._sysConfig;
}
}
export class SysConfig {
map_url: string;
product_url: string;
gis_url: string;
meta_url: string;
user_url: string;
task_url: string;
cemss_url: string;
cemss_ws_url: string;
font_size: string;
}