wangrong
2022-03-23 9e3033c25283dff92244ccc0156b3ad1ee409767
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { App, Config, Provide } from '@midwayjs/decorator';
import {
  IWebMiddleware,
  IMidwayWebNext,
  IMidwayWebApplication,
} from '@midwayjs/web';
import * as _ from 'lodash';
import { CoolConfig, RESCODE } from '@cool-midway/core';
import * as jwt from 'jsonwebtoken';
import { Context } from 'egg';
 
/**
 * 权限校验
 */
@Provide()
export class BaseAuthorityMiddleware implements IWebMiddleware {
  @Config('cool')
  coolConfig: CoolConfig;
 
  @Config('module.base')
  jwtConfig: CoolConfig;
 
  coolCache;
 
  @App()
  app: IMidwayWebApplication;
 
  resolve() {
    return async (ctx: Context, next: IMidwayWebNext) => {
      let statusCode = 200;
      let { url } = ctx;
      const { prefix } = this.coolConfig.router;
      url = url.replace(prefix, '');
      const token = ctx.get('Authorization');
      const adminUrl = '/admin/';
      // 路由地址为 admin前缀的 需要权限校验
      if (_.startsWith(url, adminUrl)) {
        try {
          ctx.admin = jwt.verify(token, this.jwtConfig.jwt.secret);
        } catch (err) {}
        // 不需要登录 无需权限校验
        if (new RegExp(`^${adminUrl}?.*/open/`).test(url)) {
          await next();
          return;
        }
        // 不需要登录 无需权限校验
        if (new RegExp(`^${adminUrl}?.*/basedeviceinfo/`).test(url)) {
          await next();
          return;
        }
        if (ctx.admin) {
          // 超管拥有所有权限
          if (ctx.admin.username == 'admin' && !ctx.admin.isRefresh) {
            await next();
            return;
          }
          // 要登录每个人都有权限的接口
          if (new RegExp(`^${adminUrl}?.*/comm/`).test(url)) {
            await next();
            return;
          }
          // 如果传的token是refreshToken则校验失败
          if (ctx.admin.isRefresh) {
            ctx.status = 401;
            ctx.body = {
              code: RESCODE.COMMFAIL,
              message: '登录失效~',
            };
            return;
          }
          // 需要动态获得缓存
          this.coolCache = await ctx.requestContext.getAsync('cool:cache');
          // 判断密码版本是否正确
          const passwordV = await this.coolCache.get(
            `admin:passwordVersion:${ctx.admin.userId}`
          );
          if (passwordV != ctx.admin.passwordVersion) {
            ctx.status = 401;
            ctx.body = {
              code: RESCODE.COMMFAIL,
              message: '登录失效~',
            };
            return;
          }
          const rToken = await this.coolCache.get(
            `admin:token:${ctx.admin.userId}`
          );
          if (!rToken) {
            ctx.status = 401;
            ctx.body = {
              code: RESCODE.COMMFAIL,
              message: '登录失效或无权限访问~',
            };
            return;
          }
          if (rToken !== token && this.coolConfig.sso) {
            statusCode = 401;
          } else {
            let perms = await this.coolCache.get(
              `admin:perms:${ctx.admin.userId}`
            );
            if (!_.isEmpty(perms)) {
              perms = JSON.parse(perms).map(e => {
                return e.replace(/:/g, '/');
              });
              if (!perms.includes(url.split('?')[0].replace('/admin/', ''))) {
                statusCode = 403;
              }
            } else {
              statusCode = 403;
            }
          }
        } else {
          statusCode = 401;
        }
        if (statusCode > 200) {
          ctx.status = statusCode;
          ctx.body = {
            code: RESCODE.COMMFAIL,
            message: '登录失效或无权限访问~',
          };
          return;
        }
      }
      await next();
    };
  }
}