forked from yoone/API
104 lines
2.7 KiB
TypeScript
104 lines
2.7 KiB
TypeScript
// src/middleware/auth.middleware.ts
|
|
import {
|
|
IMiddleware,
|
|
Middleware,
|
|
Inject,
|
|
NextFunction,
|
|
httpError,
|
|
} from '@midwayjs/core';
|
|
import { Context } from '@midwayjs/koa';
|
|
import { JwtService } from '@midwayjs/jwt'; // 引入 JwtService 类型
|
|
import { DeviceWhitelistService } from '../service/deviceWhitelist.service';
|
|
|
|
@Middleware()
|
|
export class AuthMiddleware implements IMiddleware<Context, NextFunction> {
|
|
@Inject()
|
|
jwtService: JwtService; // 注入 JwtService 实例
|
|
@Inject()
|
|
deviceWhitelistService: DeviceWhitelistService;
|
|
|
|
// 白名单配置
|
|
whiteList = [
|
|
'/user/login',
|
|
'/webhook/woocommerce',
|
|
'/logistics/getTrackingNumber',
|
|
'/logistics/getListByTrackingId',
|
|
'/product/categories/all',
|
|
'/product/category/1/attributes',
|
|
'/product/category/2/attributes',
|
|
'/product/category/3/attributes',
|
|
'/product/category/4/attributes',
|
|
'/product/list',
|
|
'/dict/items',
|
|
];
|
|
|
|
match(ctx: Context) {
|
|
return !this.isWhiteListed(ctx);
|
|
}
|
|
|
|
resolve() {
|
|
return async (ctx: Context, next: NextFunction) => {
|
|
// 判断下有没有校验信息
|
|
if (!ctx.headers['authorization']) {
|
|
throw new httpError.UnauthorizedError();
|
|
}
|
|
// 从 header 上获取校验信息
|
|
const parts = ctx.get('authorization').trim().split(' ');
|
|
|
|
if (parts.length !== 2) {
|
|
throw new httpError.UnauthorizedError();
|
|
}
|
|
|
|
const [scheme, token] = parts;
|
|
|
|
if (!/^Bearer$/i.test(scheme)) {
|
|
throw new httpError.UnauthorizedError('Invalid Token Scheme');
|
|
}
|
|
|
|
try {
|
|
// 2. 校验 JWT 并解析 payload
|
|
const decoded: any = await this.jwtService.verify(token);
|
|
|
|
const deviceId: string = decoded.deviceId;
|
|
if (!deviceId) {
|
|
throw new httpError.UnauthorizedError('Missing deviceId in token');
|
|
}
|
|
|
|
// 3. 校验设备是否在白名单
|
|
const isWhite = await this.deviceWhitelistService.isWhitelisted(
|
|
deviceId
|
|
);
|
|
if (!isWhite) {
|
|
throw new httpError.UnauthorizedError('Device not authorized');
|
|
}
|
|
} catch (error) {
|
|
throw new httpError.UnauthorizedError('Invalid or expired token');
|
|
}
|
|
|
|
if (/^Bearer$/i.test(scheme)) {
|
|
try {
|
|
//jwt.verify方法验证token是否有效
|
|
await this.jwtService.verify(token, {
|
|
complete: true,
|
|
});
|
|
} catch (error) {
|
|
throw new httpError.UnauthorizedError();
|
|
}
|
|
await next();
|
|
}
|
|
};
|
|
}
|
|
|
|
static getName(): string {
|
|
return 'authMiddleware';
|
|
}
|
|
|
|
static getPriority(): number {
|
|
return 0;
|
|
}
|
|
|
|
isWhiteListed(ctx: Context): boolean {
|
|
return this.whiteList.includes(ctx.path);
|
|
}
|
|
}
|