You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
2.1 KiB
73 lines
2.1 KiB
import { logger } from "@/logger"
|
|
import jwt from "./jwt"
|
|
import { minimatch } from "minimatch"
|
|
|
|
export const JWT_SECRET = process.env.JWT_SECRET
|
|
|
|
function matchList(list, path) {
|
|
for (const item of list) {
|
|
if (typeof item === "string" && minimatch(path, item)) {
|
|
return { matched: true, auth: false }
|
|
}
|
|
if (typeof item === "object" && minimatch(path, item.pattern)) {
|
|
return { matched: true, auth: item.auth }
|
|
}
|
|
}
|
|
return { matched: false }
|
|
}
|
|
|
|
function verifyToken(ctx) {
|
|
let token = ctx.headers["authorization"]?.replace(/^Bearer\s/, "")
|
|
if (!token) {
|
|
return { ok: false, status: -1 }
|
|
}
|
|
try {
|
|
ctx.state.user = jwt.verify(token, JWT_SECRET)
|
|
return { ok: true }
|
|
} catch {
|
|
ctx.state.user = undefined
|
|
return { ok: false }
|
|
}
|
|
}
|
|
|
|
export default function authMiddleware(options = {
|
|
whiteList: [],
|
|
blackList: []
|
|
}) {
|
|
return async (ctx, next) => {
|
|
if(ctx.session.user) {
|
|
ctx.state.user = ctx.session.user
|
|
}
|
|
// 黑名单优先生效
|
|
if (matchList(options.blackList, ctx.path).matched) {
|
|
ctx.status = 403
|
|
ctx.body = { success: false, error: "禁止访问" }
|
|
return
|
|
}
|
|
// 白名单处理
|
|
const white = matchList(options.whiteList, ctx.path)
|
|
if (white.matched) {
|
|
if (white.auth === false) {
|
|
return await next()
|
|
}
|
|
if (white.auth === "try") {
|
|
verifyToken(ctx)
|
|
return await next()
|
|
}
|
|
// true 或其他情况,必须有token
|
|
if (!verifyToken(ctx).ok) {
|
|
ctx.status = 401
|
|
ctx.body = { success: false, error: "未登录或token缺失或无效" }
|
|
return
|
|
}
|
|
return await next()
|
|
}
|
|
// 非白名单,必须有token
|
|
if (!verifyToken(ctx).ok) {
|
|
ctx.status = 401
|
|
ctx.body = { success: false, error: "未登录或token缺失或无效" }
|
|
return
|
|
}
|
|
await next()
|
|
}
|
|
}
|
|
|