2024-08-27 13:46:19 +08:00
|
|
|
import { Init, Inject, MidwayWebRouterService, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
2023-06-27 09:29:43 +08:00
|
|
|
import { IMidwayKoaContext, IWebMiddleware, NextFunction } from '@midwayjs/koa';
|
2024-07-15 00:30:33 +08:00
|
|
|
import jwt from 'jsonwebtoken';
|
2025-01-14 00:54:30 +08:00
|
|
|
import { Constants, SysPrivateSettings, SysSettingsService } from '@certd/lib-server';
|
2024-11-04 16:39:02 +08:00
|
|
|
import { logger } from '@certd/basic';
|
2024-10-07 03:21:16 +08:00
|
|
|
import { AuthService } from '../modules/sys/authority/service/auth-service.js';
|
2025-01-14 00:54:30 +08:00
|
|
|
import { OpenKeyService } from '../modules/open/service/open-key-service.js';
|
2025-01-19 00:33:34 +08:00
|
|
|
import { RoleService } from '../modules/sys/authority/service/role-service.js';
|
2023-01-29 15:26:58 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 权限校验
|
|
|
|
|
*/
|
|
|
|
|
@Provide()
|
2024-08-27 13:46:19 +08:00
|
|
|
@Scope(ScopeEnum.Singleton)
|
2023-01-29 15:26:58 +08:00
|
|
|
export class AuthorityMiddleware implements IWebMiddleware {
|
2023-06-27 09:29:43 +08:00
|
|
|
@Inject()
|
|
|
|
|
webRouterService: MidwayWebRouterService;
|
|
|
|
|
@Inject()
|
2024-08-05 12:49:44 +08:00
|
|
|
authService: AuthService;
|
2024-08-27 13:46:19 +08:00
|
|
|
@Inject()
|
2025-01-19 00:33:34 +08:00
|
|
|
roleService: RoleService;
|
|
|
|
|
@Inject()
|
2025-01-14 00:54:30 +08:00
|
|
|
openKeyService: OpenKeyService;
|
|
|
|
|
@Inject()
|
2024-08-27 13:46:19 +08:00
|
|
|
sysSettingsService: SysSettingsService;
|
|
|
|
|
|
|
|
|
|
secret: string;
|
|
|
|
|
@Init()
|
|
|
|
|
async init() {
|
|
|
|
|
const setting: SysPrivateSettings = await this.sysSettingsService.getSetting(SysPrivateSettings);
|
|
|
|
|
this.secret = setting.jwtKey;
|
|
|
|
|
}
|
2023-01-29 15:26:58 +08:00
|
|
|
|
|
|
|
|
resolve() {
|
|
|
|
|
return async (ctx: IMidwayKoaContext, next: NextFunction) => {
|
2023-06-27 09:29:43 +08:00
|
|
|
// 查询当前路由是否在路由表中注册
|
2024-07-15 00:30:33 +08:00
|
|
|
const routeInfo = await this.webRouterService.getMatchedRouterInfo(ctx.path, ctx.method);
|
2023-06-27 22:45:27 +08:00
|
|
|
if (routeInfo == null) {
|
|
|
|
|
// 404
|
|
|
|
|
await next();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-06-27 09:29:43 +08:00
|
|
|
const permission = routeInfo.summary;
|
|
|
|
|
if (permission == null || permission === '') {
|
|
|
|
|
ctx.status = 500;
|
2024-07-15 00:30:33 +08:00
|
|
|
ctx.body = Constants.res.serverError('该路由未配置权限控制:' + ctx.path);
|
2023-06-27 09:29:43 +08:00
|
|
|
return;
|
2023-01-29 15:26:58 +08:00
|
|
|
}
|
2023-06-27 09:29:43 +08:00
|
|
|
|
|
|
|
|
if (permission === Constants.per.guest) {
|
2023-01-29 15:26:58 +08:00
|
|
|
await next();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-27 09:29:43 +08:00
|
|
|
let token = ctx.get('Authorization') || '';
|
|
|
|
|
token = token.replace('Bearer ', '').trim();
|
2024-10-05 01:46:25 +08:00
|
|
|
if (!token) {
|
2023-06-27 22:45:27 +08:00
|
|
|
//尝试从cookie中获取token
|
|
|
|
|
token = ctx.cookies.get('token') || '';
|
|
|
|
|
}
|
2024-10-05 01:46:25 +08:00
|
|
|
if (!token) {
|
2023-06-27 22:45:27 +08:00
|
|
|
//尝试从query中获取token
|
|
|
|
|
token = (ctx.query.token as string) || '';
|
|
|
|
|
}
|
2023-06-27 09:29:43 +08:00
|
|
|
|
2025-01-19 00:33:34 +08:00
|
|
|
if (token) {
|
|
|
|
|
try {
|
|
|
|
|
ctx.user = jwt.verify(token, this.secret);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
logger.error('token verify error: ', err);
|
|
|
|
|
return this.notAuth(ctx);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
//找找openKey
|
|
|
|
|
const openKey = await this.doOpenHandler(ctx);
|
|
|
|
|
if (!openKey) {
|
|
|
|
|
return this.notAuth(ctx);
|
|
|
|
|
}
|
|
|
|
|
if (permission === Constants.per.open) {
|
|
|
|
|
await next();
|
2023-06-27 09:29:43 +08:00
|
|
|
return;
|
2025-01-19 00:33:34 +08:00
|
|
|
} else if (openKey.scope === 'open') {
|
|
|
|
|
return this.notAuth(ctx);
|
2023-06-27 09:29:43 +08:00
|
|
|
}
|
|
|
|
|
}
|
2025-01-19 00:33:34 +08:00
|
|
|
|
|
|
|
|
if (permission === Constants.per.authOnly) {
|
|
|
|
|
await next();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const pass = await this.authService.checkPermission(ctx, permission);
|
|
|
|
|
if (!pass) {
|
|
|
|
|
logger.info('not permission: ', ctx.req.url);
|
|
|
|
|
ctx.status = 401;
|
|
|
|
|
ctx.body = Constants.res.permission;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-01-19 01:07:20 +08:00
|
|
|
await next();
|
2023-01-29 15:26:58 +08:00
|
|
|
};
|
|
|
|
|
}
|
2025-01-14 00:54:30 +08:00
|
|
|
|
2025-01-19 00:33:34 +08:00
|
|
|
private notAuth(ctx: IMidwayKoaContext) {
|
|
|
|
|
ctx.status = 401;
|
|
|
|
|
ctx.body = Constants.res.auth;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async doOpenHandler(ctx: IMidwayKoaContext) {
|
2025-01-14 00:54:30 +08:00
|
|
|
//开放接口
|
2025-01-19 00:33:34 +08:00
|
|
|
const openKey = ctx.get('x-certd-token') || '';
|
2025-01-14 00:54:30 +08:00
|
|
|
if (!openKey) {
|
2025-01-19 00:33:34 +08:00
|
|
|
return null;
|
2025-01-14 00:54:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//校验 openKey
|
|
|
|
|
const openKeyRes = await this.openKeyService.verifyOpenKey(openKey);
|
2025-01-19 00:33:34 +08:00
|
|
|
const roles = await this.roleService.getRoleIdsByUserId(openKeyRes.userId);
|
|
|
|
|
ctx.user = { id: openKeyRes.userId, roles };
|
2025-01-14 00:54:30 +08:00
|
|
|
ctx.openKey = openKeyRes;
|
2025-01-19 00:33:34 +08:00
|
|
|
return openKeyRes;
|
2025-01-14 00:54:30 +08:00
|
|
|
}
|
2023-01-29 15:26:58 +08:00
|
|
|
}
|