问题描述
我为 express 编写了自定义装饰器。这是控制器装饰器:
export function controller(routePrefix: string) {
return function (target: Function) {
const router = AppRouter.getInstance();
for (let key in target.prototype) {
const routeHandler = target.prototype[key]; //getLogin
const path = Reflect.getMetadata(
MetadataKeys.Path,target.prototype,key
);
const method: Methods = Reflect.getMetadata(
MetadataKeys.Method,key
);
const middlewares =
Reflect.getMetadata(MetadataKeys.Middleware,key) ||
[];
if (path) {
router[method](
`${routePrefix}${path}`,...middlewares,routeHandler
);
}
}
};
}
这是 use
装饰器:
export function use(middleware: RequestHandler | jwtRequestHandler) {
return function (target: any,key: string,desc: PropertyDescriptor) {
const middlewares =
Reflect.getMetadata(MetadataKeys.Middleware,target,key) || [];
Reflect.defineMetadata(
MetadataKeys.Middleware,[...middlewares,middleware],key
);
};
}
路线如下:
@controller("/api/v1/portfolios")
@post("/")
@use(checkJwt)
@use(checkRole("admin"))
async createPortfolio(req: Request,res: Response) {
const portfolioData = req.body;
console.log("portfoliodata",portfolioData);
const userId = req.user.sub;
const portfolio = new Portfolio(portfolioData);
console.log("portfoliom");
portfolio.userId = userId;
}
express-jwt 接受请求并将 user
添加到请求对象中。
`user=req.user`
这里是 checkJwt
中间件:
export const checkJwt = jwt({
secret: jwksRsa.expressJwtSecret({
cache: true,rateLimit: true,jwksRequestsPerMinute: 10,// this link is always provided by auth0 providers
jwksUri: process.env.JWKS_URI as string,}),// this is in the API/identifier in auth0.com
audience: process.env.AUTH0_AUDIENCE,// issuer should end with "/"
issuer: process.env.ISSUER,algorithms: ["RS256"],});
但是 checkJwt 没有被执行。 checkRole
被执行,所以这意味着我的设置是正确的。由于未执行 checkJwt,因此未定义 req.user
,因此 checkRole
会捕获错误。这是checkRole
:
export const checkRole = (role: string) => (
req: Request,res: Response,next: NextFunction
) => {
let user: { [key: string]: string } = {};
user = req.user;
if (user && user[process.env.AUTH0_NAMESPACE + "/roles"].includes(role)) {
next();
} else {
return res
.status(401)
.send("You are not authorized to access this resource!");
}
};
当我从客户发布投资组合时,checkRole 发送此错误“您无权访问此资源!”。
我不知道如何让 express 执行 checkJwt。
解决方法
你需要注意你的装饰器的顺序。 The documentation 表示装饰器从上到下调用,但结果从下到上返回。
所以你的代码应该是这样的:
@post("/")
@use(checkRole("admin"))
@use(checkJwt)
async createPortfolio(req: Request,res: Response) {
//Your code
}