@yongdall/user-cookie 0.6.1 → 0.6.4
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/package.json +3 -3
- package/yongdall/user.mjs +11 -83
- package/yongdall/user.mjs.map +1 -1
package/package.json
CHANGED
package/yongdall/user.mjs
CHANGED
|
@@ -1,76 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IdentityToken, existUser } from "@yongdall/core";
|
|
2
2
|
import { k99Context } from "@yongdall/http";
|
|
3
3
|
|
|
4
|
-
//#region plugins/user-cookie/yongdall/user.
|
|
5
|
-
/** @import { UserManager } from '@yongdall/core' */
|
|
4
|
+
//#region plugins/user-cookie/yongdall/user.mts
|
|
6
5
|
const userLoggedCookie = "user-logged-token";
|
|
7
6
|
const cookieTime = 1440 * 60 * 1e3;
|
|
8
|
-
/**
|
|
9
|
-
* 使用 HMAC-SHA256 对一个或多个值进行哈希,使用 salt 作为密钥。
|
|
10
|
-
* 输出为 base64url 格式。
|
|
11
|
-
*
|
|
12
|
-
* @param {string | ArrayBuffer | ArrayBufferView<ArrayBuffer>} salt
|
|
13
|
-
* @param {string | number} value
|
|
14
|
-
* @param {...(string | number)} values
|
|
15
|
-
* @returns {Promise<string>}
|
|
16
|
-
*/
|
|
17
|
-
async function hash(salt, value, ...values) {
|
|
18
|
-
/** @type {ArrayBuffer | ArrayBufferView<ArrayBuffer>} */
|
|
19
|
-
let keyBuffer;
|
|
20
|
-
if (salt instanceof ArrayBuffer || ArrayBuffer.isView(salt)) keyBuffer = salt;
|
|
21
|
-
else if (typeof salt === "string") keyBuffer = new TextEncoder().encode(salt);
|
|
22
|
-
else throw new Error("`salt` 参数必须为字符串或 Uint8Array");
|
|
23
|
-
const cryptoKey = await crypto.subtle.importKey("raw", keyBuffer, {
|
|
24
|
-
name: "HMAC",
|
|
25
|
-
hash: "SHA-256"
|
|
26
|
-
}, false, ["sign"]);
|
|
27
|
-
/** @type {string[]} */
|
|
28
|
-
let data = [];
|
|
29
|
-
if (typeof value === "number") data.push(String(value));
|
|
30
|
-
else if (typeof value === "string") data.push(JSON.stringify(value).slice(1, -1));
|
|
31
|
-
else throw new Error("`value` 参数必须为字符串或数字");
|
|
32
|
-
for (const v of values) if (typeof v === "number") data.push(String(v));
|
|
33
|
-
else if (typeof v === "string") data.push(JSON.stringify(v).slice(1, -1));
|
|
34
|
-
const messageBuffer = new TextEncoder().encode(data.join("\n"));
|
|
35
|
-
const signature = await crypto.subtle.sign("HMAC", cryptoKey, messageBuffer);
|
|
36
|
-
return btoa(String.fromCharCode(...new Uint8Array(signature))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
*
|
|
40
|
-
* @param {string} cookie
|
|
41
|
-
* @returns {Promise<[string, boolean]?>}
|
|
42
|
-
*/
|
|
43
|
-
async function parseUserCookie(cookie) {
|
|
44
|
-
if (typeof cookie !== "string") return null;
|
|
45
|
-
const list = cookie.split(".");
|
|
46
|
-
if (list.length !== 3) return null;
|
|
47
|
-
const timestamp = Number(list[0]);
|
|
48
|
-
if (!Number.isSafeInteger(timestamp)) return null;
|
|
49
|
-
const time = Date.now() - timestamp;
|
|
50
|
-
if (time > cookieTime) return null;
|
|
51
|
-
if (await hash(await useSalt(), list[1], list[0]) !== list[2]) return null;
|
|
52
|
-
return [list[1], time > cookieTime * 2 / 3];
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
*
|
|
56
|
-
* @param {string} user
|
|
57
|
-
* @returns {Promise<string>}
|
|
58
|
-
*/
|
|
59
|
-
async function toUserCookie(user) {
|
|
60
|
-
const timestamp = Date.now();
|
|
61
|
-
return [
|
|
62
|
-
timestamp,
|
|
63
|
-
user,
|
|
64
|
-
await hash(await useSalt(), user, timestamp)
|
|
65
|
-
].join(".");
|
|
66
|
-
}
|
|
67
|
-
/** @type {UserManager['get']} */
|
|
68
7
|
const get = async () => {
|
|
69
8
|
const ctx = k99Context();
|
|
70
9
|
if (!ctx) return null;
|
|
10
|
+
if (ctx.requestHeaders.get("X-Cookie-Auth")?.trim().toLowerCase() === "disabled") return null;
|
|
71
11
|
const cookie = ctx.cookies[userLoggedCookie];
|
|
72
12
|
if (!cookie) return null;
|
|
73
|
-
const userInfo = await
|
|
13
|
+
const userInfo = await IdentityToken.parse(cookie, cookieTime);
|
|
74
14
|
if (!userInfo) {
|
|
75
15
|
ctx.clearCookie(userLoggedCookie, {
|
|
76
16
|
httpOnly: true,
|
|
@@ -78,47 +18,35 @@ const get = async () => {
|
|
|
78
18
|
});
|
|
79
19
|
return null;
|
|
80
20
|
}
|
|
81
|
-
const [userId,
|
|
21
|
+
const [userId, percent] = userInfo;
|
|
82
22
|
if (!existUser(userId)) return null;
|
|
83
|
-
if (
|
|
23
|
+
if (percent > 2 / 3) ctx.setCookie(userLoggedCookie, await IdentityToken.create(userId), {
|
|
84
24
|
httpOnly: true,
|
|
85
25
|
path: "/"
|
|
86
26
|
});
|
|
87
27
|
return userId;
|
|
88
28
|
};
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
* @param {string} userId
|
|
92
|
-
* @returns
|
|
93
|
-
*/
|
|
94
|
-
/** @type {UserManager['set']} */
|
|
95
29
|
const set = async (userId) => {
|
|
96
30
|
if (!userId) return null;
|
|
97
31
|
const ctx = k99Context();
|
|
98
32
|
if (!ctx) return null;
|
|
99
|
-
ctx.setCookie(userLoggedCookie, await
|
|
33
|
+
ctx.setCookie(userLoggedCookie, await IdentityToken.create(userId), {
|
|
100
34
|
httpOnly: true,
|
|
101
35
|
path: "/"
|
|
102
36
|
});
|
|
103
|
-
return
|
|
37
|
+
return true;
|
|
104
38
|
};
|
|
105
|
-
/**
|
|
106
|
-
*
|
|
107
|
-
* @param {string} userId
|
|
108
|
-
* @returns
|
|
109
|
-
*/
|
|
110
|
-
/** @type {UserManager['login']} */
|
|
111
39
|
const login = async (userId) => {
|
|
112
40
|
if (!userId) return null;
|
|
113
41
|
const ctx = k99Context();
|
|
114
42
|
if (!ctx) return null;
|
|
115
|
-
ctx.
|
|
43
|
+
if (ctx.requestHeaders.get("X-Cookie-Auth")?.trim().toLowerCase() === "disabled") return null;
|
|
44
|
+
ctx.setCookie(userLoggedCookie, await IdentityToken.create(userId), {
|
|
116
45
|
httpOnly: true,
|
|
117
46
|
path: "/"
|
|
118
47
|
});
|
|
119
|
-
return
|
|
48
|
+
return true;
|
|
120
49
|
};
|
|
121
|
-
/** @type {UserManager['exit']} */
|
|
122
50
|
const exit = () => {
|
|
123
51
|
const ctx = k99Context();
|
|
124
52
|
if (!ctx) return null;
|
package/yongdall/user.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.mjs","names":[],"sources":["../../../plugins/user-cookie/yongdall/user.
|
|
1
|
+
{"version":3,"file":"user.mjs","names":[],"sources":["../../../plugins/user-cookie/yongdall/user.mts"],"sourcesContent":["import type { UserManager } from '@yongdall/core'\n\nimport { existUser, IdentityToken } from '@yongdall/core';\n\nimport { k99Context } from '@yongdall/http';\n\nconst userLoggedCookie = 'user-logged-token';\nconst cookieTime = 24 * 60 * 60 * 1000;\n\nexport const get: UserManager['get'] = async () => {\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tconst cookieAuth = ctx.requestHeaders.get('X-Cookie-Auth')?.trim().toLowerCase()\n\tif (cookieAuth === 'disabled') { return null; }\n\tconst cookie = ctx.cookies[userLoggedCookie];\n\tif (!cookie) { return null; }\n\tconst userInfo = await IdentityToken.parse(cookie, cookieTime);\n\tif (!userInfo) { ctx.clearCookie(userLoggedCookie, { httpOnly: true, path: '/' }); return null; }\n\tconst [userId, percent] = userInfo;\n\tif (!existUser(userId)) { return null; }\n\tif (percent > 2 / 3) { ctx.setCookie(userLoggedCookie, await IdentityToken.create(userId), { httpOnly: true, path: '/' }); }\n\treturn userId;\n};\n\nexport const set: UserManager['set'] = async (userId) => {\n\tif (!userId) { return null; }\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tctx.setCookie(userLoggedCookie, await IdentityToken.create(userId), { httpOnly: true, path: '/' });\n\treturn true;\n};\n\nexport const login: UserManager['login'] = async (userId) => {\n\tif (!userId) { return null; }\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tconst cookieAuth = ctx.requestHeaders.get('X-Cookie-Auth')?.trim().toLowerCase()\n\tif (cookieAuth === 'disabled') { return null; }\n\tctx.setCookie(userLoggedCookie, await IdentityToken.create(userId), { httpOnly: true, path: '/' });\n\treturn true;\n};\n\nexport const exit: UserManager['exit'] = () => {\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tctx.clearCookie(userLoggedCookie, { httpOnly: true, path: '/' });\n\treturn null;\n};\n"],"mappings":";;;;AAMA,MAAM,mBAAmB;AACzB,MAAM,aAAa,OAAU,KAAK;AAElC,MAAa,MAA0B,YAAY;CAClD,MAAM,MAAM,YAAY;AACxB,KAAI,CAAC,IAAO,QAAO;AAEnB,KADmB,IAAI,eAAe,IAAI,gBAAgB,EAAE,MAAM,CAAC,aAAa,KAC7D,WAAc,QAAO;CACxC,MAAM,SAAS,IAAI,QAAQ;AAC3B,KAAI,CAAC,OAAU,QAAO;CACtB,MAAM,WAAW,MAAM,cAAc,MAAM,QAAQ,WAAW;AAC9D,KAAI,CAAC,UAAU;AAAE,MAAI,YAAY,kBAAkB;GAAE,UAAU;GAAM,MAAM;GAAK,CAAC;AAAE,SAAO;;CAC1F,MAAM,CAAC,QAAQ,WAAW;AAC1B,KAAI,CAAC,UAAU,OAAO,CAAI,QAAO;AACjC,KAAI,UAAU,IAAI,EAAK,KAAI,UAAU,kBAAkB,MAAM,cAAc,OAAO,OAAO,EAAE;EAAE,UAAU;EAAM,MAAM;EAAK,CAAC;AACzH,QAAO;;AAGR,MAAa,MAA0B,OAAO,WAAW;AACxD,KAAI,CAAC,OAAU,QAAO;CACtB,MAAM,MAAM,YAAY;AACxB,KAAI,CAAC,IAAO,QAAO;AACnB,KAAI,UAAU,kBAAkB,MAAM,cAAc,OAAO,OAAO,EAAE;EAAE,UAAU;EAAM,MAAM;EAAK,CAAC;AAClG,QAAO;;AAGR,MAAa,QAA8B,OAAO,WAAW;AAC5D,KAAI,CAAC,OAAU,QAAO;CACtB,MAAM,MAAM,YAAY;AACxB,KAAI,CAAC,IAAO,QAAO;AAEnB,KADmB,IAAI,eAAe,IAAI,gBAAgB,EAAE,MAAM,CAAC,aAAa,KAC7D,WAAc,QAAO;AACxC,KAAI,UAAU,kBAAkB,MAAM,cAAc,OAAO,OAAO,EAAE;EAAE,UAAU;EAAM,MAAM;EAAK,CAAC;AAClG,QAAO;;AAGR,MAAa,aAAkC;CAC9C,MAAM,MAAM,YAAY;AACxB,KAAI,CAAC,IAAO,QAAO;AACnB,KAAI,YAAY,kBAAkB;EAAE,UAAU;EAAM,MAAM;EAAK,CAAC;AAChE,QAAO"}
|