lrf před 11 měsíci
rodič
revize
7a089e793f

+ 3 - 3
README.md

@@ -1,8 +1,8 @@
 # 未完成:
   * [x] 1.代理请求
-	* [ ]	2.单点登录管理
-	* [ ]	3.接口鉴权
-  * [ ] 4.i18n处理
+  * [ ] 2.检查白名单
+	* [X]	3.单点登录管理
+	* [ ]	4.接口鉴权
 
   * [ ] x.对数据进行解密
     - [ ] 2.1 前端生成 加密字符串 并加密 post 请求下的数据, 将加密串带在token中: ${str}:${token}

+ 2 - 1
src/configuration.ts

@@ -31,7 +31,8 @@ export class MainConfiguration {
 
   async onReady() {
     // add middleware
-    this.app.useMiddleware([ReportMiddleware, SetLocaleToCtxMiddleware]);
+    this.app.getMiddleware().insertFirst(SetLocaleToCtxMiddleware);
+    this.app.useMiddleware([ReportMiddleware]);
     this.app.useFilter([CustomErrorFilter]);
   }
 }

+ 14 - 5
src/controller/home.controller.ts

@@ -2,6 +2,7 @@ import { All, Controller, Get, Inject, Put } from '@midwayjs/core';
 import { Context } from '@midwayjs/koa';
 import { ProxyService } from '../service/proxy.service';
 import { FrameworkErrorEnum, LoginError } from '../error/login.error';
+import { SingleSignOnService } from '../service/singleSignOn.service';
 @Controller('/')
 export class HomeController {
   @Inject()
@@ -10,6 +11,9 @@ export class HomeController {
   @Inject()
   service: ProxyService;
 
+  @Inject()
+  singleSignOnService: SingleSignOnService;
+
   @Get('/')
   async home(): Promise<string> {
     return 'proxy starting....';
@@ -21,10 +25,15 @@ export class HomeController {
   @All('/**')
   async proxy() {
     // const rb = this.service.getRequstBase();
-    // 1.
-    throw new LoginError(FrameworkErrorEnum.TEST);
-    // return await this.service.toProxy();
-    // return false;
-    // return 'in proxy';
+    // TODO:1.检查请求是否在白名单
+    const inWhiteList = true;
+    if (!inWhiteList) {
+      // 2.不在白名单上则检查登录
+      await this.singleSignOnService.index();
+      // 2-1.通过检查(不报异常中断程序)即可以发送请求
+      return await this.service.toProxy();
+    }
+    // 3.发送请求
+    return await this.service.toProxy();
   }
 }

+ 4 - 1
src/error/login.error.ts

@@ -1,9 +1,12 @@
 import { MidwayError, registerErrorCode } from '@midwayjs/core';
 // 需保持一致的标识,具体看error的readme
 const code = 'LoginError';
-
+// 写这个enum只是为了能有提示,不随便瞎写,都规范起来
 export enum LoginErroCode {
   TEST = 'TEST',
+  NOT_LOGIN = 'NOT_LOGIN',
+  ACCOUNT_HAS_EXPIRED = 'ACCOUNT_HAS_EXPIRED',
+  ACCOUNT_LOGGED_IN_ELESWHERE = 'ACCOUNT_LOGGED_IN_ELESWHERE',
 }
 export const FrameworkErrorEnum = registerErrorCode(code, LoginErroCode);
 

+ 5 - 0
src/locales/zh_cn/error/LoginError.ts

@@ -3,6 +3,11 @@ import { toUpper } from 'lodash';
 const codePrefix = 'LoginError';
 const obj = {
   TEST: '测试异常',
+  NOT_LOGIN: '未检测到登录信息,请登录!',
+  ACCOUNT_HAS_EXPIRED: '账号登录已失效,请重新登录!',
+  ACCOUNT_LOGGED_IN_ELESWHERE: '本账号已在其他地方登录,请重新登录!',
+  // '该用户已被禁用',
+  // '当前角色下的用户无法使用'
 };
 const listObject = {};
 Object.keys(obj).map(i => {

+ 51 - 6
src/service/singleSignOn.service.ts

@@ -1,22 +1,67 @@
-import { Config, Inject, InjectClient, Provide } from '@midwayjs/core';
+import { Config, Inject, Provide } from '@midwayjs/core';
 import { JwtService } from '@midwayjs/jwt';
 import { Context } from '@midwayjs/koa';
 import { get } from 'lodash';
-import { LoginError } from '../error/login.error';
+import { FrameworkErrorEnum, LoginError } from '../error/login.error';
+import * as Crypto from 'crypto-js';
+import { RedisService } from '@midwayjs/redis';
 
 @Provide()
 export class SingleSignOnService {
   @Inject()
-  ctx: Context;
+  private ctx: Context;
+  @Config('loginSign')
+  private loginSign;
+  @Config('jwt.secret')
+  private jwtSecret;
+  @Config('jwt.expiresIn')
+  private jwtExpiresIn;
   @Inject()
-  jwtService: JwtService;
-  async index() {
+  private jwtService: JwtService;
+  @Inject()
+  private redisService: RedisService;
+  /**
+   * 单点登录检查
+   */
+  async index(): Promise<void> {
     let user;
     const token: any = get(this.ctx.request, 'header.token');
     if (token) {
       const data = this.jwtService.decodeSync(token);
       if (data) user = data;
     }
-    if (!user) throw new LoginError('TEST');
+    if (!user) throw new LoginError(FrameworkErrorEnum.NOT_LOGIN);
+    const { _id, role, login_code } = user;
+    if (!login_code) throw new LoginError(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 LoginError(FrameworkErrorEnum.ACCOUNT_HAS_EXPIRED);
+    // 判断是否一致
+    if (code === redisCode) {
+      // 一致,延时
+      await this.redisService.expire(rediskey, this.jwtExpiresIn);
+    } else {
+      throw new LoginError(FrameworkErrorEnum.ACCOUNT_LOGGED_IN_ELESWHERE);
+    }
+  }
+  /**
+   * 检查路由是否在白名单中
+   */
+  inWhiteList(): boolean {
+    const whiteList = {
+      uri: '/login',
+      desc: '',
+    };
+
+    return true;
   }
 }