@pangza/auth 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/AuthUtil.d.ts +78 -0
- package/dist/AuthUtil.d.ts.map +1 -0
- package/dist/AuthUtil.js +356 -0
- package/dist/AuthUtil.js.map +1 -0
- package/dist/context.d.ts +10 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +15 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +38 -0
- package/dist/errors.js.map +1 -0
- package/dist/flag.d.ts +3 -0
- package/dist/flag.d.ts.map +1 -0
- package/dist/flag.js +7 -0
- package/dist/flag.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +162 -0
- package/dist/index.js.map +1 -0
- package/dist/store.d.ts +72 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +173 -0
- package/dist/store.js.map +1 -0
- package/dist/token.d.ts +16 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +81 -0
- package/dist/token.js.map +1 -0
- package/dist/types.d.ts +144 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -4
package/README.md
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @pangza/auth
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Auth / 登录态与权限
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { AuthOptions, AuthSession, LoginId, LoginOptions, ResolvedAuthOptions } from "./types";
|
|
2
|
+
/** 合并并保存 Auth 配置;配置了 redis 则优先使用 Redis 会话库 */
|
|
3
|
+
export declare function configureAuth(options?: AuthOptions): void;
|
|
4
|
+
/** 读取当前鉴权配置 */
|
|
5
|
+
export declare function getAuthOptions(): ResolvedAuthOptions;
|
|
6
|
+
/** 校验会话是否因绝对过期 / 闲置过期而失效 */
|
|
7
|
+
export declare function isSessionExpired(session: AuthSession, options?: ResolvedAuthOptions): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* 类 Sa-Token 的静态工具(AuthUtil)。
|
|
10
|
+
* 业务侧通过它完成登录、取 token、校验登录/角色/权限。
|
|
11
|
+
*/
|
|
12
|
+
export declare class AuthUtil {
|
|
13
|
+
/**
|
|
14
|
+
* 登录:创建会话并返回 token。
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* AuthUtil.login(id, ['admin'], ['user:read'])
|
|
18
|
+
* AuthUtil.login(id, { roles, permissions, device: 'web', username })
|
|
19
|
+
*/
|
|
20
|
+
static login(loginId: LoginId, rolesOrOptions?: string[] | LoginOptions, permissions?: string[], profile?: {
|
|
21
|
+
username?: string;
|
|
22
|
+
avatar?: string;
|
|
23
|
+
device?: string;
|
|
24
|
+
}): Promise<string>;
|
|
25
|
+
private static syncContext;
|
|
26
|
+
/**
|
|
27
|
+
* 注销当前(或指定)token 会话
|
|
28
|
+
* @param token 不传则注销当前请求 token
|
|
29
|
+
*/
|
|
30
|
+
static logout(token?: string): Promise<void>;
|
|
31
|
+
/** 按账号注销其全部会话 */
|
|
32
|
+
static logoutByLoginId(loginId: LoginId): Promise<void>;
|
|
33
|
+
/** 按账号 + 设备注销 */
|
|
34
|
+
static logoutByDevice(loginId: LoginId, device: string): Promise<void>;
|
|
35
|
+
/** 获取当前请求 token(优先上下文,其次请求头/Cookie) */
|
|
36
|
+
static getTokenValue(): string | null;
|
|
37
|
+
/**
|
|
38
|
+
* 从请求解析 token:
|
|
39
|
+
* 1. tokenName 请求头(如 satoken)
|
|
40
|
+
* 2. Authorization / 自定义 header(可带 Bearer 前缀)
|
|
41
|
+
* 3. Cookie[tokenName]
|
|
42
|
+
*/
|
|
43
|
+
static readTokenFromRequest(req: {
|
|
44
|
+
headers: Record<string, unknown>;
|
|
45
|
+
cookies?: Record<string, unknown>;
|
|
46
|
+
}): string | null;
|
|
47
|
+
/**
|
|
48
|
+
* 加载并校验会话;过期清理;可选刷新 lastActiveTime。
|
|
49
|
+
*/
|
|
50
|
+
static loadSession(token: string | null, options?: {
|
|
51
|
+
touch?: boolean;
|
|
52
|
+
}): Promise<AuthSession | null>;
|
|
53
|
+
/** 获取当前有效会话;过期会清理并返回 null */
|
|
54
|
+
static getSession(): Promise<AuthSession | null>;
|
|
55
|
+
/** 是否已登录 */
|
|
56
|
+
static isLogin(): Promise<boolean>;
|
|
57
|
+
/** 校验已登录,否则抛 NotLoginError;返回 loginId */
|
|
58
|
+
static checkLogin(): Promise<LoginId>;
|
|
59
|
+
/** 获取登录账号(未登录抛错) */
|
|
60
|
+
static getLoginId(): Promise<LoginId>;
|
|
61
|
+
/** 获取登录账号;未登录返回 null */
|
|
62
|
+
static getLoginIdDefaultNull(): Promise<LoginId | null>;
|
|
63
|
+
/** 当前登录设备 */
|
|
64
|
+
static getLoginDevice(): Promise<string | undefined>;
|
|
65
|
+
/** 当前角色列表 */
|
|
66
|
+
static getRoleList(): Promise<string[]>;
|
|
67
|
+
/** 当前权限列表 */
|
|
68
|
+
static getPermissionList(): Promise<string[]>;
|
|
69
|
+
/** 是否拥有指定角色 */
|
|
70
|
+
static hasRole(role: string): Promise<boolean>;
|
|
71
|
+
/** 是否拥有指定权限 */
|
|
72
|
+
static hasPermission(permission: string): Promise<boolean>;
|
|
73
|
+
/** 校验角色,失败抛 NotRoleError */
|
|
74
|
+
static checkRole(role: string): Promise<void>;
|
|
75
|
+
/** 校验权限,失败抛 NotPermissionError */
|
|
76
|
+
static checkPermission(permission: string): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=AuthUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthUtil.d.ts","sourceRoot":"","sources":["../src/AuthUtil.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,YAAY,EACZ,mBAAmB,EACpB,MAAM,SAAS,CAAC;AA6BjB,8CAA8C;AAC9C,wBAAgB,aAAa,CAAC,OAAO,GAAE,WAAgB,GAAG,IAAI,CA8B7D;AAED,eAAe;AACf,wBAAgB,cAAc,IAAI,mBAAmB,CAEpD;AAuBD,4BAA4B;AAC5B,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,mBAAiC,GACzC,OAAO,CAWT;AAED;;;GAGG;AACH,qBAAa,QAAQ;IACnB;;;;;;OAMG;WACU,KAAK,CAChB,OAAO,EAAE,OAAO,EAChB,cAAc,GAAE,MAAM,EAAE,GAAG,YAAiB,EAC5C,WAAW,GAAE,MAAM,EAAO,EAC1B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAChE,OAAO,CAAC,MAAM,CAAC;IAqElB,OAAO,CAAC,MAAM,CAAC,WAAW;IAQ1B;;;OAGG;WACU,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlD,iBAAiB;WACJ,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7D,iBAAiB;WACJ,cAAc,CACzB,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAWhB,uCAAuC;IACvC,MAAM,CAAC,aAAa,IAAI,MAAM,GAAG,IAAI;IAOrC;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE;QAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,GAAG,MAAM,GAAG,IAAI;IAkCjB;;OAEG;WACU,WAAW,CACtB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAoB,GAC7C,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IA2B9B,6BAA6B;WAChB,UAAU,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAgBtD,YAAY;WACC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAIxC,yCAAyC;WAC5B,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAM3C,oBAAoB;WACP,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAI3C,wBAAwB;WACX,qBAAqB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAI7D,aAAa;WACA,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAI1D,aAAa;WACA,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAI7C,aAAa;WACA,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAInD,eAAe;WACF,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIpD,eAAe;WACF,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhE,4BAA4B;WACf,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnD,kCAAkC;WACrB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMhE"}
|
package/dist/AuthUtil.js
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthUtil = void 0;
|
|
4
|
+
exports.configureAuth = configureAuth;
|
|
5
|
+
exports.getAuthOptions = getAuthOptions;
|
|
6
|
+
exports.isSessionExpired = isSessionExpired;
|
|
7
|
+
const context_1 = require("./context");
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
const store_1 = require("./store");
|
|
10
|
+
const token_1 = require("./token");
|
|
11
|
+
/** 默认会话时长:2 小时(毫秒) */
|
|
12
|
+
const DEFAULT_TIMEOUT = 2 * 60 * 60 * 1000;
|
|
13
|
+
const DEFAULT_JWT_SECRET = "pangza-admin-express-jwt-secret";
|
|
14
|
+
/** 运行时鉴权配置(由 Auth(options) 写入) */
|
|
15
|
+
let authOptions = {
|
|
16
|
+
tokenName: "satoken",
|
|
17
|
+
header: "Authorization",
|
|
18
|
+
tokenPrefix: "Bearer",
|
|
19
|
+
timeout: DEFAULT_TIMEOUT,
|
|
20
|
+
activityTimeout: -1,
|
|
21
|
+
allowConcurrentLogin: true,
|
|
22
|
+
isShare: false,
|
|
23
|
+
tokenStyle: "uuid",
|
|
24
|
+
jwtSecret: DEFAULT_JWT_SECRET,
|
|
25
|
+
jwtAlgorithm: "HS256",
|
|
26
|
+
ignore: [],
|
|
27
|
+
readCookie: true,
|
|
28
|
+
checkMode: "OR",
|
|
29
|
+
};
|
|
30
|
+
function resolveExpireTime(timeoutMs, now = Date.now()) {
|
|
31
|
+
if (timeoutMs < 0)
|
|
32
|
+
return Number.MAX_SAFE_INTEGER;
|
|
33
|
+
return now + timeoutMs;
|
|
34
|
+
}
|
|
35
|
+
/** 合并并保存 Auth 配置;配置了 redis 则优先使用 Redis 会话库 */
|
|
36
|
+
function configureAuth(options = {}) {
|
|
37
|
+
authOptions = {
|
|
38
|
+
...authOptions,
|
|
39
|
+
...options,
|
|
40
|
+
tokenName: options.tokenName ?? authOptions.tokenName,
|
|
41
|
+
header: options.header ?? authOptions.header,
|
|
42
|
+
tokenPrefix: options.tokenPrefix !== undefined
|
|
43
|
+
? options.tokenPrefix
|
|
44
|
+
: authOptions.tokenPrefix,
|
|
45
|
+
timeout: options.timeout ?? authOptions.timeout,
|
|
46
|
+
activityTimeout: options.activityTimeout ?? authOptions.activityTimeout,
|
|
47
|
+
allowConcurrentLogin: options.allowConcurrentLogin ?? authOptions.allowConcurrentLogin,
|
|
48
|
+
isShare: options.isShare ?? authOptions.isShare,
|
|
49
|
+
tokenStyle: options.tokenStyle ?? authOptions.tokenStyle,
|
|
50
|
+
createToken: options.createToken ?? authOptions.createToken,
|
|
51
|
+
jwtSecret: options.jwtSecret ?? authOptions.jwtSecret,
|
|
52
|
+
jwtAlgorithm: options.jwtAlgorithm ?? authOptions.jwtAlgorithm,
|
|
53
|
+
ignore: options.ignore ?? authOptions.ignore,
|
|
54
|
+
readCookie: options.readCookie ?? authOptions.readCookie,
|
|
55
|
+
redis: options.redis ?? authOptions.redis,
|
|
56
|
+
checkMode: options.checkMode ?? authOptions.checkMode,
|
|
57
|
+
};
|
|
58
|
+
if (options.redis) {
|
|
59
|
+
(0, store_1.setSessionStore)(new store_1.RedisStore(options.redis));
|
|
60
|
+
}
|
|
61
|
+
else if (options.redis === undefined && !authOptions.redis) {
|
|
62
|
+
(0, store_1.setSessionStore)(new store_1.MemoryStore());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** 读取当前鉴权配置 */
|
|
66
|
+
function getAuthOptions() {
|
|
67
|
+
return authOptions;
|
|
68
|
+
}
|
|
69
|
+
function normalizeLoginArgs(rolesOrOptions, permissions, profile) {
|
|
70
|
+
if (rolesOrOptions &&
|
|
71
|
+
!Array.isArray(rolesOrOptions) &&
|
|
72
|
+
typeof rolesOrOptions === "object") {
|
|
73
|
+
return rolesOrOptions;
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
roles: rolesOrOptions ?? [],
|
|
77
|
+
permissions: permissions ?? [],
|
|
78
|
+
username: profile?.username,
|
|
79
|
+
avatar: profile?.avatar,
|
|
80
|
+
device: profile?.device,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/** 校验会话是否因绝对过期 / 闲置过期而失效 */
|
|
84
|
+
function isSessionExpired(session, options = authOptions) {
|
|
85
|
+
const now = Date.now();
|
|
86
|
+
if (now > session.expireTime)
|
|
87
|
+
return true;
|
|
88
|
+
if (options.activityTimeout >= 0 &&
|
|
89
|
+
now - (session.lastActiveTime || session.createTime) >
|
|
90
|
+
options.activityTimeout) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 类 Sa-Token 的静态工具(AuthUtil)。
|
|
97
|
+
* 业务侧通过它完成登录、取 token、校验登录/角色/权限。
|
|
98
|
+
*/
|
|
99
|
+
class AuthUtil {
|
|
100
|
+
/**
|
|
101
|
+
* 登录:创建会话并返回 token。
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* AuthUtil.login(id, ['admin'], ['user:read'])
|
|
105
|
+
* AuthUtil.login(id, { roles, permissions, device: 'web', username })
|
|
106
|
+
*/
|
|
107
|
+
static async login(loginId, rolesOrOptions = [], permissions = [], profile) {
|
|
108
|
+
const opt = normalizeLoginArgs(rolesOrOptions, permissions, profile);
|
|
109
|
+
const store = (0, store_1.getSessionStore)();
|
|
110
|
+
const timeout = opt.timeout ?? authOptions.timeout;
|
|
111
|
+
const device = opt.device;
|
|
112
|
+
const now = Date.now();
|
|
113
|
+
// is-share:复用已有有效 token(同账号 + 同设备)
|
|
114
|
+
if (authOptions.isShare) {
|
|
115
|
+
const tokens = await store.listTokensByLoginId(loginId);
|
|
116
|
+
for (const t of tokens) {
|
|
117
|
+
const old = await store.getByToken(t);
|
|
118
|
+
if (!old || isSessionExpired(old)) {
|
|
119
|
+
if (old)
|
|
120
|
+
await store.removeByToken(t);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (device && old.device && old.device !== device)
|
|
124
|
+
continue;
|
|
125
|
+
if (!device && old.device)
|
|
126
|
+
continue;
|
|
127
|
+
old.roles = opt.roles ?? old.roles;
|
|
128
|
+
old.permissions = opt.permissions ?? old.permissions;
|
|
129
|
+
old.username = opt.username ?? old.username;
|
|
130
|
+
old.avatar = opt.avatar ?? old.avatar;
|
|
131
|
+
old.expireTime = resolveExpireTime(timeout, now);
|
|
132
|
+
old.lastActiveTime = now;
|
|
133
|
+
await store.set(old);
|
|
134
|
+
this.syncContext(old.token, old);
|
|
135
|
+
return old.token;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// 不允许并发:挤掉旧登录
|
|
139
|
+
if (!authOptions.allowConcurrentLogin) {
|
|
140
|
+
if (device) {
|
|
141
|
+
const tokens = await store.listTokensByLoginId(loginId);
|
|
142
|
+
for (const t of tokens) {
|
|
143
|
+
const old = await store.getByToken(t);
|
|
144
|
+
if (old && (!old.device || old.device === device)) {
|
|
145
|
+
await store.removeByToken(t);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
await store.removeByLoginId(loginId);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const token = await (0, token_1.createAuthToken)(authOptions, {
|
|
154
|
+
loginId,
|
|
155
|
+
device,
|
|
156
|
+
timeout,
|
|
157
|
+
});
|
|
158
|
+
const session = {
|
|
159
|
+
token,
|
|
160
|
+
loginId,
|
|
161
|
+
device,
|
|
162
|
+
roles: opt.roles ?? [],
|
|
163
|
+
permissions: opt.permissions ?? [],
|
|
164
|
+
username: opt.username,
|
|
165
|
+
avatar: opt.avatar,
|
|
166
|
+
createTime: now,
|
|
167
|
+
expireTime: resolveExpireTime(timeout, now),
|
|
168
|
+
lastActiveTime: now,
|
|
169
|
+
};
|
|
170
|
+
await store.set(session);
|
|
171
|
+
this.syncContext(token, session);
|
|
172
|
+
return token;
|
|
173
|
+
}
|
|
174
|
+
static syncContext(token, session) {
|
|
175
|
+
const ctx = (0, context_1.getAuthStore)();
|
|
176
|
+
if (ctx) {
|
|
177
|
+
ctx.token = token;
|
|
178
|
+
ctx.session = session;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* 注销当前(或指定)token 会话
|
|
183
|
+
* @param token 不传则注销当前请求 token
|
|
184
|
+
*/
|
|
185
|
+
static async logout(token) {
|
|
186
|
+
const value = token ?? this.getTokenValue();
|
|
187
|
+
if (value)
|
|
188
|
+
await (0, store_1.getSessionStore)().removeByToken(value);
|
|
189
|
+
const ctx = (0, context_1.getAuthStore)();
|
|
190
|
+
if (ctx && (!token || ctx.token === token)) {
|
|
191
|
+
ctx.token = null;
|
|
192
|
+
ctx.session = null;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/** 按账号注销其全部会话 */
|
|
196
|
+
static async logoutByLoginId(loginId) {
|
|
197
|
+
await (0, store_1.getSessionStore)().removeByLoginId(loginId);
|
|
198
|
+
}
|
|
199
|
+
/** 按账号 + 设备注销 */
|
|
200
|
+
static async logoutByDevice(loginId, device) {
|
|
201
|
+
const store = (0, store_1.getSessionStore)();
|
|
202
|
+
const tokens = await store.listTokensByLoginId(loginId);
|
|
203
|
+
for (const t of tokens) {
|
|
204
|
+
const session = await store.getByToken(t);
|
|
205
|
+
if (session?.device === device) {
|
|
206
|
+
await store.removeByToken(t);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/** 获取当前请求 token(优先上下文,其次请求头/Cookie) */
|
|
211
|
+
static getTokenValue() {
|
|
212
|
+
const store = (0, context_1.getAuthStore)();
|
|
213
|
+
if (store?.token)
|
|
214
|
+
return store.token;
|
|
215
|
+
if (store?.req)
|
|
216
|
+
return this.readTokenFromRequest(store.req);
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* 从请求解析 token:
|
|
221
|
+
* 1. tokenName 请求头(如 satoken)
|
|
222
|
+
* 2. Authorization / 自定义 header(可带 Bearer 前缀)
|
|
223
|
+
* 3. Cookie[tokenName]
|
|
224
|
+
*/
|
|
225
|
+
static readTokenFromRequest(req) {
|
|
226
|
+
const tryRaw = (raw) => {
|
|
227
|
+
if (typeof raw !== "string" || !raw.trim())
|
|
228
|
+
return null;
|
|
229
|
+
const value = raw.trim();
|
|
230
|
+
const prefix = authOptions.tokenPrefix;
|
|
231
|
+
if (prefix && value.startsWith(`${prefix} `)) {
|
|
232
|
+
return value.slice(prefix.length + 1).trim() || null;
|
|
233
|
+
}
|
|
234
|
+
return value || null;
|
|
235
|
+
};
|
|
236
|
+
// 1. tokenName header(Sa-Token 常用)
|
|
237
|
+
const byName = tryRaw(req.headers[authOptions.tokenName.toLowerCase()]);
|
|
238
|
+
if (byName)
|
|
239
|
+
return byName;
|
|
240
|
+
// 2. Authorization / 兼容 header
|
|
241
|
+
const headerName = authOptions.header.toLowerCase();
|
|
242
|
+
if (headerName !== authOptions.tokenName.toLowerCase()) {
|
|
243
|
+
const byHeader = tryRaw(req.headers[headerName]);
|
|
244
|
+
if (byHeader)
|
|
245
|
+
return byHeader;
|
|
246
|
+
}
|
|
247
|
+
// 3. Cookie
|
|
248
|
+
if (authOptions.readCookie) {
|
|
249
|
+
const cookies = req.cookies;
|
|
250
|
+
if (cookies) {
|
|
251
|
+
const byCookie = tryRaw(cookies[authOptions.tokenName]);
|
|
252
|
+
if (byCookie)
|
|
253
|
+
return byCookie;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* 加载并校验会话;过期清理;可选刷新 lastActiveTime。
|
|
260
|
+
*/
|
|
261
|
+
static async loadSession(token, options = { touch: true }) {
|
|
262
|
+
if (!token)
|
|
263
|
+
return null;
|
|
264
|
+
if (!(0, token_1.verifyAuthToken)(authOptions, token)) {
|
|
265
|
+
await (0, store_1.getSessionStore)().removeByToken(token);
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
const session = await (0, store_1.getSessionStore)().getByToken(token);
|
|
269
|
+
if (!session)
|
|
270
|
+
return null;
|
|
271
|
+
// 兼容旧会话无 lastActiveTime
|
|
272
|
+
if (!session.lastActiveTime) {
|
|
273
|
+
session.lastActiveTime = session.createTime;
|
|
274
|
+
}
|
|
275
|
+
if (isSessionExpired(session)) {
|
|
276
|
+
await (0, store_1.getSessionStore)().removeByToken(token);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
if (options.touch !== false) {
|
|
280
|
+
session.lastActiveTime = Date.now();
|
|
281
|
+
await (0, store_1.getSessionStore)().touch(session);
|
|
282
|
+
}
|
|
283
|
+
return session;
|
|
284
|
+
}
|
|
285
|
+
/** 获取当前有效会话;过期会清理并返回 null */
|
|
286
|
+
static async getSession() {
|
|
287
|
+
const ctx = (0, context_1.getAuthStore)();
|
|
288
|
+
if (ctx?.session) {
|
|
289
|
+
if (isSessionExpired(ctx.session)) {
|
|
290
|
+
await this.logout(ctx.session.token);
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
// 请求内已 touch 过则不重复写
|
|
294
|
+
return ctx.session;
|
|
295
|
+
}
|
|
296
|
+
const token = this.getTokenValue();
|
|
297
|
+
const session = await this.loadSession(token);
|
|
298
|
+
if (ctx)
|
|
299
|
+
ctx.session = session;
|
|
300
|
+
return session;
|
|
301
|
+
}
|
|
302
|
+
/** 是否已登录 */
|
|
303
|
+
static async isLogin() {
|
|
304
|
+
return (await this.getSession()) !== null;
|
|
305
|
+
}
|
|
306
|
+
/** 校验已登录,否则抛 NotLoginError;返回 loginId */
|
|
307
|
+
static async checkLogin() {
|
|
308
|
+
const session = await this.getSession();
|
|
309
|
+
if (!session)
|
|
310
|
+
throw new errors_1.NotLoginError();
|
|
311
|
+
return session.loginId;
|
|
312
|
+
}
|
|
313
|
+
/** 获取登录账号(未登录抛错) */
|
|
314
|
+
static async getLoginId() {
|
|
315
|
+
return this.checkLogin();
|
|
316
|
+
}
|
|
317
|
+
/** 获取登录账号;未登录返回 null */
|
|
318
|
+
static async getLoginIdDefaultNull() {
|
|
319
|
+
return (await this.getSession())?.loginId ?? null;
|
|
320
|
+
}
|
|
321
|
+
/** 当前登录设备 */
|
|
322
|
+
static async getLoginDevice() {
|
|
323
|
+
return (await this.getSession())?.device;
|
|
324
|
+
}
|
|
325
|
+
/** 当前角色列表 */
|
|
326
|
+
static async getRoleList() {
|
|
327
|
+
return (await this.getSession())?.roles ?? [];
|
|
328
|
+
}
|
|
329
|
+
/** 当前权限列表 */
|
|
330
|
+
static async getPermissionList() {
|
|
331
|
+
return (await this.getSession())?.permissions ?? [];
|
|
332
|
+
}
|
|
333
|
+
/** 是否拥有指定角色 */
|
|
334
|
+
static async hasRole(role) {
|
|
335
|
+
return (await this.getRoleList()).includes(role);
|
|
336
|
+
}
|
|
337
|
+
/** 是否拥有指定权限 */
|
|
338
|
+
static async hasPermission(permission) {
|
|
339
|
+
return (await this.getPermissionList()).includes(permission);
|
|
340
|
+
}
|
|
341
|
+
/** 校验角色,失败抛 NotRoleError */
|
|
342
|
+
static async checkRole(role) {
|
|
343
|
+
await this.checkLogin();
|
|
344
|
+
if (!(await this.hasRole(role)))
|
|
345
|
+
throw new errors_1.NotRoleError(`无角色: ${role}`);
|
|
346
|
+
}
|
|
347
|
+
/** 校验权限,失败抛 NotPermissionError */
|
|
348
|
+
static async checkPermission(permission) {
|
|
349
|
+
await this.checkLogin();
|
|
350
|
+
if (!(await this.hasPermission(permission))) {
|
|
351
|
+
throw new errors_1.NotPermissionError(`无权限: ${permission}`);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
exports.AuthUtil = AuthUtil;
|
|
356
|
+
//# sourceMappingURL=AuthUtil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthUtil.js","sourceRoot":"","sources":["../src/AuthUtil.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2
|
+
import type { AuthContextStore } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* 请求级鉴权上下文。
|
|
5
|
+
* 中间件里 run 一次后,同一次请求内的 AuthUtil 都能取到当前 req/token/session。
|
|
6
|
+
*/
|
|
7
|
+
export declare const authContext: AsyncLocalStorage<AuthContextStore>;
|
|
8
|
+
/** 获取当前请求的鉴权上下文;不在 Auth 中间件内时返回 undefined */
|
|
9
|
+
export declare function getAuthStore(): AuthContextStore | undefined;
|
|
10
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,WAAW,qCAA4C,CAAC;AAErE,6CAA6C;AAC7C,wBAAgB,YAAY,IAAI,gBAAgB,GAAG,SAAS,CAE3D"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authContext = void 0;
|
|
4
|
+
exports.getAuthStore = getAuthStore;
|
|
5
|
+
const async_hooks_1 = require("async_hooks");
|
|
6
|
+
/**
|
|
7
|
+
* 请求级鉴权上下文。
|
|
8
|
+
* 中间件里 run 一次后,同一次请求内的 AuthUtil 都能取到当前 req/token/session。
|
|
9
|
+
*/
|
|
10
|
+
exports.authContext = new async_hooks_1.AsyncLocalStorage();
|
|
11
|
+
/** 获取当前请求的鉴权上下文;不在 Auth 中间件内时返回 undefined */
|
|
12
|
+
function getAuthStore() {
|
|
13
|
+
return exports.authContext.getStore();
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":";;;AAUA,oCAEC;AAZD,6CAAgD;AAGhD;;;GAGG;AACU,QAAA,WAAW,GAAG,IAAI,+BAAiB,EAAoB,CAAC;AAErE,6CAA6C;AAC7C,SAAgB,YAAY;IAC1B,OAAO,mBAAW,CAAC,QAAQ,EAAE,CAAC;AAChC,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ResponseCode } from "@pangza/core/types/enums";
|
|
2
|
+
/** 鉴权相关错误基类,携带业务响应码 */
|
|
3
|
+
export declare class AuthError extends Error {
|
|
4
|
+
readonly code: ResponseCode;
|
|
5
|
+
constructor(message: string, code: ResponseCode);
|
|
6
|
+
}
|
|
7
|
+
/** 未登录 */
|
|
8
|
+
export declare class NotLoginError extends AuthError {
|
|
9
|
+
constructor(message?: string);
|
|
10
|
+
}
|
|
11
|
+
/** 无权限 */
|
|
12
|
+
export declare class NotPermissionError extends AuthError {
|
|
13
|
+
constructor(message?: string);
|
|
14
|
+
}
|
|
15
|
+
/** 无角色 */
|
|
16
|
+
export declare class NotRoleError extends AuthError {
|
|
17
|
+
constructor(message?: string);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,uBAAuB;AACvB,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;gBAEhB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY;CAKhD;AAED,UAAU;AACV,qBAAa,aAAc,SAAQ,SAAS;gBAC9B,OAAO,SAAQ;CAI5B;AAED,UAAU;AACV,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,OAAO,SAAS;CAI7B;AAED,UAAU;AACV,qBAAa,YAAa,SAAQ,SAAS;gBAC7B,OAAO,SAAS;CAI7B"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NotRoleError = exports.NotPermissionError = exports.NotLoginError = exports.AuthError = void 0;
|
|
4
|
+
const enums_1 = require("@pangza/core/types/enums");
|
|
5
|
+
/** 鉴权相关错误基类,携带业务响应码 */
|
|
6
|
+
class AuthError extends Error {
|
|
7
|
+
constructor(message, code) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "AuthError";
|
|
10
|
+
this.code = code;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.AuthError = AuthError;
|
|
14
|
+
/** 未登录 */
|
|
15
|
+
class NotLoginError extends AuthError {
|
|
16
|
+
constructor(message = "未登录") {
|
|
17
|
+
super(message, enums_1.ResponseCode.UNAUTHORIZED);
|
|
18
|
+
this.name = "NotLoginError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.NotLoginError = NotLoginError;
|
|
22
|
+
/** 无权限 */
|
|
23
|
+
class NotPermissionError extends AuthError {
|
|
24
|
+
constructor(message = "无此权限") {
|
|
25
|
+
super(message, enums_1.ResponseCode.FORBIDDEN);
|
|
26
|
+
this.name = "NotPermissionError";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.NotPermissionError = NotPermissionError;
|
|
30
|
+
/** 无角色 */
|
|
31
|
+
class NotRoleError extends AuthError {
|
|
32
|
+
constructor(message = "无此角色") {
|
|
33
|
+
super(message, enums_1.ResponseCode.FORBIDDEN);
|
|
34
|
+
this.name = "NotRoleError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.NotRoleError = NotRoleError;
|
|
38
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,oDAAwD;AAExD,uBAAuB;AACvB,MAAa,SAAU,SAAQ,KAAK;IAGlC,YAAY,OAAe,EAAE,IAAkB;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AARD,8BAQC;AAED,UAAU;AACV,MAAa,aAAc,SAAQ,SAAS;IAC1C,YAAY,OAAO,GAAG,KAAK;QACzB,KAAK,CAAC,OAAO,EAAE,oBAAY,CAAC,YAAY,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AALD,sCAKC;AAED,UAAU;AACV,MAAa,kBAAmB,SAAQ,SAAS;IAC/C,YAAY,OAAO,GAAG,MAAM;QAC1B,KAAK,CAAC,OAAO,EAAE,oBAAY,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AALD,gDAKC;AAED,UAAU;AACV,MAAa,YAAa,SAAQ,SAAS;IACzC,YAAY,OAAO,GAAG,MAAM;QAC1B,KAAK,CAAC,OAAO,EAAE,oBAAY,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AALD,oCAKC"}
|
package/dist/flag.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.d.ts","sourceRoot":"","sources":["../src/flag.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/flag.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AUTH_MIDDLEWARE_FLAG = void 0;
|
|
4
|
+
/** 用于标记 Auth 中间件,供 Application 识别是否已注册鉴权模块 */
|
|
5
|
+
var moduleFlags_1 = require("@pangza/core/moduleFlags");
|
|
6
|
+
Object.defineProperty(exports, "AUTH_MIDDLEWARE_FLAG", { enumerable: true, get: function () { return moduleFlags_1.AUTH_MIDDLEWARE_FLAG; } });
|
|
7
|
+
//# sourceMappingURL=flag.js.map
|
package/dist/flag.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.js","sourceRoot":"","sources":["../src/flag.ts"],"names":[],"mappings":";;;AAAA,8CAA8C;AAC9C,wDAAgE;AAAvD,mHAAA,oBAAoB,OAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NextFunction, Request, Response } from "express";
|
|
2
|
+
import type { AuthOptions } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* ignore 路径匹配(类 Ant / glob):
|
|
5
|
+
* - `/api/user/login` 精确,或该路径下的子路径
|
|
6
|
+
* - `/api/pub/**` 以 `/api/pub` 开头的全部接口
|
|
7
|
+
* - `/api/pub/*` 仅一层:`/api/pub/xxx`,不含更深
|
|
8
|
+
* - `/api/aes*` 前缀(尾部单个 *)
|
|
9
|
+
*/
|
|
10
|
+
export declare function matchesIgnore(path: string, ignore?: string[]): boolean;
|
|
11
|
+
/** 是否命中 Auth 全局 ignore(优先级最高) */
|
|
12
|
+
export declare function isGloballyIgnored(path: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Auth 中间件工厂(类 Sa-Token)。
|
|
15
|
+
* 只负责解析 token、注入请求上下文,不强制登录;
|
|
16
|
+
* 需要登录的接口请在业务里调用 AuthUtil.checkLogin()。
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* Auth({
|
|
20
|
+
* tokenName: 'satoken',
|
|
21
|
+
* timeout: 30 * 24 * 60 * 60 * 1000,
|
|
22
|
+
* activityTimeout: -1,
|
|
23
|
+
* allowConcurrentLogin: false,
|
|
24
|
+
* isShare: false,
|
|
25
|
+
* tokenStyle: 'uuid', // 或 'jwt'
|
|
26
|
+
* jwtSecret: 'change-me',
|
|
27
|
+
* })
|
|
28
|
+
*/
|
|
29
|
+
export default function Auth(options?: AuthOptions): (req: Request, _res: Response, next: NextFunction) => void;
|
|
30
|
+
export { AuthUtil, getAuthOptions, isSessionExpired } from "./AuthUtil";
|
|
31
|
+
export { AUTH_MIDDLEWARE_FLAG } from "./flag";
|
|
32
|
+
export { AuthError, NotLoginError, NotPermissionError, NotRoleError, } from "./errors";
|
|
33
|
+
export { createAuthToken, generateStyleToken, verifyAuthToken } from "./token";
|
|
34
|
+
export type { AuthOptions, AuthSession, LoginId, LoginOptions, TokenStyle, AuthCheckMode, ResolvedAuthOptions, } from "./types";
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAI1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAqB3C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,OAAO,CAK1E;AA+DD,iCAAiC;AACjC,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,OAAO,GAAE,WAAgB,SAG3B,OAAO,QAAQ,QAAQ,QAAQ,YAAY,UAgCrE;AAED,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EACL,SAAS,EACT,aAAa,EACb,kBAAkB,EAClB,YAAY,GACb,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/E,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,YAAY,EACZ,UAAU,EACV,aAAa,EACb,mBAAmB,GACpB,MAAM,SAAS,CAAC"}
|