mirror of
https://github.com/certd/certd.git
synced 2026-06-29 16:05:15 +08:00
154 lines
4.4 KiB
TypeScript
154 lines
4.4 KiB
TypeScript
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;
|
||
}
|
||
|
||
const token = this.getTokenFromRequest(ctx);
|
||
|
||
if (token) {
|
||
try {
|
||
ctx.user = jwt.verify(token, this.secret);
|
||
} catch (err) {
|
||
logger.error("token verify error: ", err);
|
||
return this.notAuth(ctx);
|
||
}
|
||
} else {
|
||
if (permission === Constants.per.guestOptionalAuth) {
|
||
await next();
|
||
return;
|
||
}
|
||
//找找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 error,need user scope");
|
||
}
|
||
}
|
||
|
||
if (permission === Constants.per.authOnly) {
|
||
await next();
|
||
return;
|
||
}
|
||
if (permission === Constants.per.guestOptionalAuth) {
|
||
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;
|
||
}
|
||
|
||
private getTokenFromRequest(ctx: IMidwayKoaContext) {
|
||
let token = ctx.get("Authorization") || "";
|
||
token = token.replace("Bearer ", "").trim();
|
||
if (token) {
|
||
return 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") {
|
||
return value.trim();
|
||
}
|
||
}
|
||
}
|
||
|
||
return (ctx.query.token as string) || "";
|
||
}
|
||
|
||
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;
|
||
}
|
||
}
|