如何保证一个系统只有一个用户可以登录(api.service.ts、app.config.ts)

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);
                // console.log(userinfo);
                this.areaServ.getByKey(userinfo.areaCode).then(area => {
                  // console.log(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 {
        //非退出登录 且 token未过期 
        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");
        // return "scsqxzhfyjszx";
        // return "neimeng";
    }

    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");
    }

    // true为过期 留出10秒空余量
    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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值