Files
certd/packages/ui/certd-server/src/middleware/authority.ts
T
2026-03-15 18:26:49 +08:00

144 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Init, Inject, MidwayWebRouterService, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { IMidwayKoaContext, IWebMiddleware, NextFunction } from '@midwayjs/koa';
import jwt from 'jsonwebtoken';
import { Constants, SysPrivateSettings, SysSettingsService } from '@certd/lib-server';
import { logger } from '@certd/basic';
import { AuthService } from '../modules/sys/authority/service/auth-service.js';
import { OpenKeyService } from '../modules/open/service/open-key-service.js';
import { RoleService } from '../modules/sys/authority/service/role-service.js';
/**
* 权限校验
*/
@Provide()
@Scope(ScopeEnum.Singleton)
export class AuthorityMiddleware implements IWebMiddleware {
@Inject()
webRouterService: MidwayWebRouterService;
@Inject()
authService: AuthService;
@Inject()
roleService: RoleService;
@Inject()
openKeyService: OpenKeyService;
@Inject()
sysSettingsService: SysSettingsService;
secret: string;
@Init()
async init() {
const setting: SysPrivateSettings = await this.sysSettingsService.getSetting(SysPrivateSettings);
this.secret = setting.jwtKey;
}
resolve() {
return async (ctx: IMidwayKoaContext, next: NextFunction) => {
// 查询当前路由是否在路由表中注册
const routeInfo = await this.webRouterService.getMatchedRouterInfo(ctx.path, ctx.method);
if (routeInfo == null) {
// 404
await next();
return;
}
let permission = routeInfo.description || '';
permission = permission.trim().split(' ')[0];
if (permission == null || permission === '') {
ctx.status = 500;
ctx.body = Constants.res.serverError('该路由未配置权限控制:' + ctx.path);
return;
}
if (permission === Constants.per.guest) {
await next();
return;
}
let token = ctx.get('Authorization') || '';
token = token.replace('Bearer ', '').trim();
if (!token) {
//尝试从cookie中获取token
const cookie = ctx.headers.cookie;
if (cookie) {
const items = cookie.split(';');
for (const item of items) {
if (!item || !item.trim()) {
continue;
}
const [key, value] = item.split('=');
if (key.trim() === 'certd_token') {
token = value.trim();
break;
}
}
}
}
if (!token) {
//尝试从query中获取token
token = (ctx.query.token as string) || '';
}
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();
return;
} else if (openKey.scope === 'open') {
return this.notAuth(ctx, 'open key scope errorneed user scope');
}
}
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 = 200;
ctx.body = Constants.res.permission;
return;
}
await next();
};
}
private notAuth(ctx: IMidwayKoaContext, message?: string) {
ctx.status = 401;
ctx.body = Constants.res.auth;
if (message) {
// @ts-ignore
ctx.body.message =message;
}
return;
}
async doOpenHandler(ctx: IMidwayKoaContext) {
//开放接口
const openKey = ctx.get('x-certd-token') || '';
if (!openKey) {
return null;
}
//校验 openKey
const openKeyRes = await this.openKeyService.verifyOpenKey(openKey);
let roles = [1]
if (!openKeyRes.projectId || openKeyRes.projectId <= 0) {
roles = await this.roleService.getRoleIdsByUserId(openKeyRes.userId);
}
ctx.user = { id: openKeyRes.userId, roles ,projectId:openKeyRes.projectId};
ctx.openKey = openKeyRes;
return openKeyRes;
}
}