@yongdall/user-cookie 0.5.0 → 0.5.2
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 +2 -2
- package/yongdall/user.mjs +4 -4
- package/yongdall/user.mjs.map +1 -1
package/package.json
CHANGED
package/yongdall/user.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { existUser,
|
|
1
|
+
import { existUser, useSalt } from "@yongdall/core";
|
|
2
2
|
import { k99Context } from "@yongdall/http";
|
|
3
3
|
|
|
4
4
|
//#region plugins/user-cookie/yongdall/user.mjs
|
|
5
|
-
/** @import {
|
|
5
|
+
/** @import { UserManager } from '@yongdall/core' */
|
|
6
6
|
const userLoggedCookie = "user-logged-token";
|
|
7
7
|
const cookieTime = 1440 * 60 * 1e3;
|
|
8
8
|
/**
|
|
@@ -48,7 +48,7 @@ async function parseUserCookie(cookie) {
|
|
|
48
48
|
if (!Number.isSafeInteger(timestamp)) return null;
|
|
49
49
|
const time = Date.now() - timestamp;
|
|
50
50
|
if (time > cookieTime) return null;
|
|
51
|
-
if (await hash(
|
|
51
|
+
if (await hash(await useSalt(), list[1], list[0]) !== list[2]) return null;
|
|
52
52
|
return [list[1], time > cookieTime * 2 / 3];
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
@@ -61,7 +61,7 @@ async function toUserCookie(user) {
|
|
|
61
61
|
return [
|
|
62
62
|
timestamp,
|
|
63
63
|
user,
|
|
64
|
-
await hash(
|
|
64
|
+
await hash(await useSalt(), user, timestamp)
|
|
65
65
|
].join(".");
|
|
66
66
|
}
|
|
67
67
|
/** @type {UserManager['get']} */
|
package/yongdall/user.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user.mjs","names":[],"sources":["../../../plugins/user-cookie/yongdall/user.mjs"],"sourcesContent":["/** @import {
|
|
1
|
+
{"version":3,"file":"user.mjs","names":[],"sources":["../../../plugins/user-cookie/yongdall/user.mjs"],"sourcesContent":["/** @import { UserManager } from '@yongdall/core' */\nimport { existUser, useSalt } from '@yongdall/core';\n\nimport { k99Context } from '@yongdall/http';\n\nconst userLoggedCookie = 'user-logged-token';\nconst cookieTime = 24 * 60 * 60 * 1000;\n\n\n\n/**\n * 使用 HMAC-SHA256 对一个或多个值进行哈希,使用 salt 作为密钥。\n * 输出为 base64url 格式。\n *\n * @param {string | ArrayBuffer | ArrayBufferView<ArrayBuffer>} salt\n * @param {string | number} value\n * @param {...(string | number)} values\n * @returns {Promise<string>}\n */\nasync function hash(salt, value, ...values) {\n\t// 1. 准备密钥(salt)\n\t/** @type {ArrayBuffer | ArrayBufferView<ArrayBuffer>} */\n\tlet keyBuffer;\n\tif (salt instanceof ArrayBuffer || ArrayBuffer.isView(salt)) {\n\t\tkeyBuffer = salt;\n\t} else if (typeof salt === 'string') {\n\t\tkeyBuffer = new TextEncoder().encode(salt);\n\t} else {\n\t\tthrow new Error('`salt` 参数必须为字符串或 Uint8Array');\n\t}\n\n\t// 2. 导入 HMAC 密钥\n\tconst cryptoKey = await crypto.subtle.importKey(\n\t\t'raw',\n\t\tkeyBuffer,\n\t\t{ name: 'HMAC', hash: 'SHA-256' },\n\t\tfalse,\n\t\t['sign']\n\t);\n\n\t// 3. 构造输入数据\n\t/** @type {string[]} */\n\tlet data = [];\n\n\t// 处理第一个 value\n\tif (typeof value === 'number') {\n\t\tdata.push(String(value));\n\t} else if (typeof value === 'string') {\n\t\t// JSON.stringify(value).slice(1, -1) 相当于去掉引号,等价于直接编码字符串内容\n\t\tdata.push(JSON.stringify(value).slice(1, -1));\n\t} else {\n\t\tthrow new Error('`value` 参数必须为字符串或数字');\n\t}\n\n\t// 处理后续 values\n\tfor (const v of values) {\n\t\tif (typeof v === 'number') {\n\t\t\tdata.push(String(v));\n\t\t} else if (typeof v === 'string') {\n\t\t\tdata.push(JSON.stringify(v).slice(1, -1));\n\t\t}\n\t}\n\n\t// 合并所有数据\n\tconst messageBuffer = new TextEncoder().encode(data.join('\\n'));\n\n\t// 4. 生成 HMAC\n\tconst signature = await crypto.subtle.sign('HMAC', cryptoKey, messageBuffer);\n\n\t// 5. 转为 base64url 格式\n\tconst base64 = btoa(String.fromCharCode(...new Uint8Array(signature)));\n\treturn base64\n\t\t.replace(/\\+/g, '-')\n\t\t.replace(/\\//g, '_')\n\t\t.replace(/=+$/, ''); // 移除填充\n}\n/**\n * \n * @param {string} cookie \n * @returns {Promise<[string, boolean]?>}\n */\nasync function parseUserCookie(cookie) {\n\tif (typeof cookie !== 'string') { return null; }\n\tconst list = cookie.split('.');\n\tif (list.length !== 3) { return null; }\n\tconst timestamp = Number(list[0]);\n\tif (!Number.isSafeInteger(timestamp)) { return null; }\n\tconst time = Date.now() - timestamp;\n\tif (time > cookieTime) { return null; }\n\tconst salt = await useSalt();\n\tif (await hash(salt, list[1], list[0]) !== list[2]) { return null; }\n\treturn [list[1], time > cookieTime * 2 / 3];\n}\n\n/**\n * \n * @param {string} user \n * @returns {Promise<string>}\n */\nasync function toUserCookie(user) {\n\tconst timestamp = Date.now();\n\tconst salt = await useSalt();\n\treturn [timestamp, user, await hash(salt, user, timestamp)].join('.');\n}\n/** @type {UserManager['get']} */\nexport const get = async () => {\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tconst cookie = ctx.cookies[userLoggedCookie];\n\tif (!cookie) { return null; }\n\tconst userInfo = await parseUserCookie(cookie);\n\tif (!userInfo) { ctx.clearCookie(userLoggedCookie, { httpOnly: true, path: '/' }); return null; }\n\tconst [userId, reset] = userInfo;\n\tif (!existUser(userId)) { return null; }\n\tif (reset) { ctx.setCookie(userLoggedCookie, await toUserCookie(userId), { httpOnly: true, path: '/' }); }\n\treturn userId;\n};\n/**\n * \n * @param {string} userId \n * @returns \n */\n/** @type {UserManager['set']} */\nexport const set = async (userId) => {\n\tif (!userId) { return null; }\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tctx.setCookie(userLoggedCookie, await toUserCookie(userId), { httpOnly: true, path: '/' });\n\treturn userId;\n};\n/**\n * \n * @param {string} userId \n * @returns \n */\n/** @type {UserManager['login']} */\nexport const login = async (userId) => {\n\tif (!userId) { return null; }\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tctx.setCookie(userLoggedCookie, await toUserCookie(userId), { httpOnly: true, path: '/' });\n\treturn userId;\n};\n/** @type {UserManager['exit']} */\nexport const exit = () => {\n\tconst ctx = k99Context();\n\tif (!ctx) { return null; }\n\tctx.clearCookie(userLoggedCookie, { httpOnly: true, path: '/' });\n\treturn null;\n};\n"],"mappings":"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"}
|