123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import { Config, Inject, Provide } from '@midwayjs/core';
- import { FrameworkErrorEnum, GetModel, ServiceError } from 'free-midway-component';
- import { get, isEqual, upperFirst } from 'lodash';
- import { LoginDTO, LoginType, UPwdDTO } from '../interface/login.interface';
- import { RoleService } from '../service/system/role.service';
- import { RedisService } from '@midwayjs/redis';
- import * as Crypto from 'crypto-js';
- import { Context } from '@midwayjs/koa';
- @Provide()
- export class LoginService {
- @Inject()
- roleService: RoleService;
- @Inject()
- ctx: Context;
- @Config('loginSign')
- loginSign;
- @Config('jwt.secret')
- jwtSecret;
- @Config('jwt.expiresIn')
- jwtExpiresIn;
- @Inject()
- redisService: RedisService;
- async onePointLogin(loginVo) {
- const { _id, role } = loginVo;
- const rediskey = `${this.loginSign}:${role}:${_id}`;
- // 随机字符串 验证用户登录用
- const str = this.randomStr();
- // 拼接成token内的登录code 加密前数据
- const val = `${rediskey}:${str}`;
- // 加密后存入token内
- const code = Crypto.AES.encrypt(val, this.jwtSecret).toString();
- // 设置redis登录记录 将 随机字符串存在redis中. 验证时需要将加密的字符串解密,解密后和redis中的对比验证
- await this.redisService.set(rediskey, str, 'EX', this.jwtExpiresIn);
- return code;
- }
- async onePointCheck() {
- const user = this.ctx.user;
- if (!user) throw new ServiceError('未检测到登录信息,请重新登录!', FrameworkErrorEnum.NOT_LOGIN);
- const { _id, role, login_code } = user;
- if (!login_code) throw new ServiceError('未检测到登录标识,请重新登录!', FrameworkErrorEnum.NOT_LOGIN);
- // 解密
- const decodeResult = Crypto.AES.decrypt(login_code, this.jwtSecret);
- const decode = Crypto.enc.Utf8.stringify(decodeResult).toString();
- // 取出code
- const codeArr = decode.split(':');
- const code = codeArr[codeArr.length - 1];
- // 拼接redis的key
- const rediskey = `${this.loginSign}:${role}:${_id}`;
- // 取出当前记录在案的 code
- const redisCode = await this.redisService.get(rediskey);
- if(!redisCode) throw new ServiceError('账号登录已失效,请重新登录!', FrameworkErrorEnum.NOT_LOGIN);
- // 判断是否一致
- if (code === redisCode) {
- // 一致,延时
- await this.redisService.expire(rediskey, this.jwtExpiresIn);
- } else {
- throw new ServiceError('本账号已在其他地方登录,请重新登录!', FrameworkErrorEnum.NOT_LOGIN);
- }
- }
- /**
- * 账密登录
- * @param data 用户名和密码
- * @param type 用户类型
- * @returns 用户信息/空值
- */
- async loginByAccount(data: LoginDTO, type: LoginType) {
- const model = GetModel(upperFirst(type));
- const user = await model.findOne({ account: data.account }, '+password').lean();
- if (!user) throw new ServiceError('未找到用户信息', FrameworkErrorEnum.NOT_FOUND_DATA);
- await this.checkAccountCanLogin(user, type);
- if (!isEqual(user.password.secret, data.password)) throw new ServiceError('密码错误', FrameworkErrorEnum.SERVICE_FAULT);
- return user;
- }
- /**
- * 检查用户是否可以登录(从用户本身和角色检查)
- * @param user 用户信息
- * @param type 用户类型
- */
- async checkAccountCanLogin(user, type: LoginType) {
- // 判断是否可以使用:
- // 管理员: 超级管理员无视,直接往下; 普通管理员需要查看is_use是不是'0'
- // 其他用户需要看status是不是'1';
- if (type === 'Admin') {
- if (get(user, 'is_super') === '1') {
- if (get(user, 'is_use') === '1') throw new ServiceError('该用户已被禁用', FrameworkErrorEnum.SERVICE_FAULT);
- }
- } else {
- if (get(user, 'status') !== '1') throw new ServiceError('该用户已被禁用', FrameworkErrorEnum.SERVICE_FAULT);
- const role = await this.roleService.findOne({ code: type, is_use: '0' });
- if (!role) throw new ServiceError('当前角色下的用户无法使用!', FrameworkErrorEnum.SERVICE_FAULT);
- }
- }
- async updatePwd(data: UPwdDTO, type: LoginType) {
- const model = GetModel(upperFirst(type));
- const user = await model.findById(data._id);
- if (!user) new ServiceError('未找到用户信息!', FrameworkErrorEnum.DATA_NOT_FOUND);
- user.password = data.password;
- await user.save();
- }
- // 需要改的时候再用
- // async wxAppLogin(openid: string) {
- // const tables = ['Doctor', 'Nurse', 'Patient'];
- // let user;
- // let role;
- // for (const table of tables) {
- // const model = GetModel(upperFirst(table));
- // user = await model.findOne({ openid }).lean();
- // if (user) {
- // role = table;
- // break;
- // }
- // }
- // if (user) return { ...user, role };
- // throw new ServiceError('未找到用户信息!', FrameworkErrorEnum.NOT_FOUND_DATA);
- // }
- randomStr(len = 32) {
- return Math.random().toString(36).slice(-len);
- }
- }
|