@vlian/csrf 0.1.1
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/dist/index.cjs +159 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +144 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSRF 防护工具
|
|
3
|
+
* 提供 CSRF Token 的生成、存储和验证功能
|
|
4
|
+
*/ /**
|
|
5
|
+
* CSRF Token 存储接口
|
|
6
|
+
*/ "use strict";
|
|
7
|
+
Object.defineProperty(exports, "__esModule", {
|
|
8
|
+
value: true
|
|
9
|
+
});
|
|
10
|
+
function _export(target, all) {
|
|
11
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
_export(exports, {
|
|
17
|
+
get CSRFTokenManager () {
|
|
18
|
+
return CSRFTokenManager;
|
|
19
|
+
},
|
|
20
|
+
get getCSRFManager () {
|
|
21
|
+
return getCSRFManager;
|
|
22
|
+
},
|
|
23
|
+
get initCSRFManager () {
|
|
24
|
+
return initCSRFManager;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
function _define_property(obj, key, value) {
|
|
28
|
+
if (key in obj) {
|
|
29
|
+
Object.defineProperty(obj, key, {
|
|
30
|
+
value: value,
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true
|
|
34
|
+
});
|
|
35
|
+
} else {
|
|
36
|
+
obj[key] = value;
|
|
37
|
+
}
|
|
38
|
+
return obj;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 默认 Token 存储(使用 Cookie)
|
|
42
|
+
*/ let CookieTokenStorage = class CookieTokenStorage {
|
|
43
|
+
getToken() {
|
|
44
|
+
if (typeof document === 'undefined') {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const cookies = document.cookie.split(';');
|
|
48
|
+
for (const cookie of cookies){
|
|
49
|
+
const [name, value] = cookie.trim().split('=');
|
|
50
|
+
if (name === this.cookieName) {
|
|
51
|
+
return decodeURIComponent(value);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
setToken(token) {
|
|
57
|
+
if (typeof document === 'undefined') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// 设置 Cookie(HttpOnly 由服务端设置,这里只设置客户端可访问的)
|
|
61
|
+
document.cookie = `${this.cookieName}=${encodeURIComponent(token)}; path=/; SameSite=Strict`;
|
|
62
|
+
}
|
|
63
|
+
clearToken() {
|
|
64
|
+
if (typeof document === 'undefined') {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
document.cookie = `${this.cookieName}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
68
|
+
}
|
|
69
|
+
constructor(cookieName = 'csrf-token'){
|
|
70
|
+
_define_property(this, "cookieName", void 0);
|
|
71
|
+
this.cookieName = cookieName;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* 内存 Token 存储(用于 SSR 或测试)
|
|
76
|
+
*/ let MemoryTokenStorage = class MemoryTokenStorage {
|
|
77
|
+
getToken() {
|
|
78
|
+
return this.token;
|
|
79
|
+
}
|
|
80
|
+
setToken(token) {
|
|
81
|
+
this.token = token;
|
|
82
|
+
}
|
|
83
|
+
clearToken() {
|
|
84
|
+
this.token = null;
|
|
85
|
+
}
|
|
86
|
+
constructor(){
|
|
87
|
+
_define_property(this, "token", null);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
let CSRFTokenManager = class CSRFTokenManager {
|
|
91
|
+
/**
|
|
92
|
+
* 获取 CSRF Token
|
|
93
|
+
*/ async getToken() {
|
|
94
|
+
if (this.getTokenFn) {
|
|
95
|
+
try {
|
|
96
|
+
return await Promise.resolve(this.getTokenFn());
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.warn('CSRF Token 获取失败:', error);
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 从存储中获取
|
|
103
|
+
return this.storage.getToken();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 设置 CSRF Token
|
|
107
|
+
*/ setToken(token) {
|
|
108
|
+
this.storage.setToken(token);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 验证 CSRF Token
|
|
112
|
+
*/ async validateToken(token) {
|
|
113
|
+
if (this.validateTokenFn) {
|
|
114
|
+
try {
|
|
115
|
+
return await Promise.resolve(this.validateTokenFn(token));
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.warn('CSRF Token 验证失败:', error);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// 默认验证:检查存储中的 Token 是否匹配
|
|
122
|
+
const storedToken = this.storage.getToken();
|
|
123
|
+
return storedToken !== null && storedToken === token;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 清除 CSRF Token
|
|
127
|
+
*/ clearToken() {
|
|
128
|
+
this.storage.clearToken();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* 获取请求头名称
|
|
132
|
+
*/ getHeaderName() {
|
|
133
|
+
return this.headerName;
|
|
134
|
+
}
|
|
135
|
+
constructor(config){
|
|
136
|
+
_define_property(this, "storage", void 0);
|
|
137
|
+
_define_property(this, "headerName", void 0);
|
|
138
|
+
_define_property(this, "cookieName", void 0);
|
|
139
|
+
_define_property(this, "getTokenFn", void 0);
|
|
140
|
+
_define_property(this, "validateTokenFn", void 0);
|
|
141
|
+
this.headerName = config?.headerName ?? 'X-CSRF-Token';
|
|
142
|
+
this.cookieName = config?.cookieName ?? 'csrf-token';
|
|
143
|
+
this.storage = config?.storage ?? (typeof document !== 'undefined' ? new CookieTokenStorage(this.cookieName) : new MemoryTokenStorage());
|
|
144
|
+
this.getTokenFn = config?.getToken;
|
|
145
|
+
this.validateTokenFn = config?.validateToken;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* 全局 CSRF Token 管理器实例
|
|
150
|
+
*/ let globalCSRFManager = null;
|
|
151
|
+
function initCSRFManager(config) {
|
|
152
|
+
globalCSRFManager = new CSRFTokenManager(config);
|
|
153
|
+
return globalCSRFManager;
|
|
154
|
+
}
|
|
155
|
+
function getCSRFManager() {
|
|
156
|
+
return globalCSRFManager;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * CSRF 防护工具\n * 提供 CSRF Token 的生成、存储和验证功能\n */\n\n/**\n * CSRF Token 存储接口\n */\nexport interface CSRFTokenStorage {\n /**\n * 获取 Token\n */\n getToken(): string | null;\n /**\n * 设置 Token\n */\n setToken(token: string): void;\n /**\n * 清除 Token\n */\n clearToken(): void;\n}\n\n/**\n * 默认 Token 存储(使用 Cookie)\n */\nclass CookieTokenStorage implements CSRFTokenStorage {\n private cookieName: string;\n\n constructor(cookieName: string = 'csrf-token') {\n this.cookieName = cookieName;\n }\n\n getToken(): string | null {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const cookies = document.cookie.split(';');\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split('=');\n if (name === this.cookieName) {\n return decodeURIComponent(value);\n }\n }\n return null;\n }\n\n setToken(token: string): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n // 设置 Cookie(HttpOnly 由服务端设置,这里只设置客户端可访问的)\n document.cookie = `${this.cookieName}=${encodeURIComponent(token)}; path=/; SameSite=Strict`;\n }\n\n clearToken(): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n document.cookie = `${this.cookieName}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n\n/**\n * 内存 Token 存储(用于 SSR 或测试)\n */\nclass MemoryTokenStorage implements CSRFTokenStorage {\n private token: string | null = null;\n\n getToken(): string | null {\n return this.token;\n }\n\n setToken(token: string): void {\n this.token = token;\n }\n\n clearToken(): void {\n this.token = null;\n }\n}\n\n/**\n * CSRF Token 管理器\n */\nexport class CSRFTokenManager {\n private storage: CSRFTokenStorage;\n private headerName: string;\n private cookieName: string;\n private getTokenFn?: () => string | Promise<string>;\n private validateTokenFn?: (token: string) => boolean | Promise<boolean>;\n\n constructor(config?: {\n storage?: CSRFTokenStorage;\n headerName?: string;\n cookieName?: string;\n getToken?: () => string | Promise<string>;\n validateToken?: (token: string) => boolean | Promise<boolean>;\n }) {\n this.headerName = config?.headerName ?? 'X-CSRF-Token';\n this.cookieName = config?.cookieName ?? 'csrf-token';\n this.storage = config?.storage ?? (typeof document !== 'undefined' \n ? new CookieTokenStorage(this.cookieName)\n : new MemoryTokenStorage());\n this.getTokenFn = config?.getToken;\n this.validateTokenFn = config?.validateToken;\n }\n\n /**\n * 获取 CSRF Token\n */\n async getToken(): Promise<string | null> {\n if (this.getTokenFn) {\n try {\n return await Promise.resolve(this.getTokenFn());\n } catch (error) {\n console.warn('CSRF Token 获取失败:', error);\n return null;\n }\n }\n\n // 从存储中获取\n return this.storage.getToken();\n }\n\n /**\n * 设置 CSRF Token\n */\n setToken(token: string): void {\n this.storage.setToken(token);\n }\n\n /**\n * 验证 CSRF Token\n */\n async validateToken(token: string): Promise<boolean> {\n if (this.validateTokenFn) {\n try {\n return await Promise.resolve(this.validateTokenFn(token));\n } catch (error) {\n console.warn('CSRF Token 验证失败:', error);\n return false;\n }\n }\n\n // 默认验证:检查存储中的 Token 是否匹配\n const storedToken = this.storage.getToken();\n return storedToken !== null && storedToken === token;\n }\n\n /**\n * 清除 CSRF Token\n */\n clearToken(): void {\n this.storage.clearToken();\n }\n\n /**\n * 获取请求头名称\n */\n getHeaderName(): string {\n return this.headerName;\n }\n}\n\n/**\n * 全局 CSRF Token 管理器实例\n */\nlet globalCSRFManager: CSRFTokenManager | null = null;\n\n/**\n * 初始化 CSRF Token 管理器\n */\nexport function initCSRFManager(config?: {\n storage?: CSRFTokenStorage;\n headerName?: string;\n cookieName?: string;\n getToken?: () => string | Promise<string>;\n validateToken?: (token: string) => boolean | Promise<boolean>;\n}): CSRFTokenManager {\n globalCSRFManager = new CSRFTokenManager(config);\n return globalCSRFManager;\n}\n\n/**\n * 获取全局 CSRF Token 管理器\n */\nexport function getCSRFManager(): CSRFTokenManager | null {\n return globalCSRFManager;\n}\n"],"names":["CSRFTokenManager","getCSRFManager","initCSRFManager","CookieTokenStorage","getToken","document","cookies","cookie","split","name","value","trim","cookieName","decodeURIComponent","setToken","token","encodeURIComponent","clearToken","MemoryTokenStorage","getTokenFn","Promise","resolve","error","console","warn","storage","validateToken","validateTokenFn","storedToken","getHeaderName","headerName","config","globalCSRFManager"],"mappings":"AAAA;;;CAGC,GAED;;CAEC;;;;;;;;;;;QAiFYA;eAAAA;;QAsGGC;eAAAA;;QAdAC;eAAAA;;;;;;;;;;;;;;;;AAzJhB;;CAEC,GACD,IAAA,AAAMC,qBAAN,MAAMA;IAOJC,WAA0B;QACxB,IAAI,OAAOC,aAAa,aAAa;YACnC,OAAO;QACT;QAEA,MAAMC,UAAUD,SAASE,MAAM,CAACC,KAAK,CAAC;QACtC,KAAK,MAAMD,UAAUD,QAAS;YAC5B,MAAM,CAACG,MAAMC,MAAM,GAAGH,OAAOI,IAAI,GAAGH,KAAK,CAAC;YAC1C,IAAIC,SAAS,IAAI,CAACG,UAAU,EAAE;gBAC5B,OAAOC,mBAAmBH;YAC5B;QACF;QACA,OAAO;IACT;IAEAI,SAASC,KAAa,EAAQ;QAC5B,IAAI,OAAOV,aAAa,aAAa;YACnC;QACF;QAEA,0CAA0C;QAC1CA,SAASE,MAAM,GAAG,GAAG,IAAI,CAACK,UAAU,CAAC,CAAC,EAAEI,mBAAmBD,OAAO,yBAAyB,CAAC;IAC9F;IAEAE,aAAmB;QACjB,IAAI,OAAOZ,aAAa,aAAa;YACnC;QACF;QAEAA,SAASE,MAAM,GAAG,GAAG,IAAI,CAACK,UAAU,CAAC,gDAAgD,CAAC;IACxF;IAlCA,YAAYA,aAAqB,YAAY,CAAE;QAF/C,uBAAQA,cAAR,KAAA;QAGE,IAAI,CAACA,UAAU,GAAGA;IACpB;AAiCF;AAEA;;CAEC,GACD,IAAA,AAAMM,qBAAN,MAAMA;IAGJd,WAA0B;QACxB,OAAO,IAAI,CAACW,KAAK;IACnB;IAEAD,SAASC,KAAa,EAAQ;QAC5B,IAAI,CAACA,KAAK,GAAGA;IACf;IAEAE,aAAmB;QACjB,IAAI,CAACF,KAAK,GAAG;IACf;;QAZA,uBAAQA,SAAuB;;AAajC;AAKO,IAAA,AAAMf,mBAAN,MAAMA;IAuBX;;GAEC,GACD,MAAMI,WAAmC;QACvC,IAAI,IAAI,CAACe,UAAU,EAAE;YACnB,IAAI;gBACF,OAAO,MAAMC,QAAQC,OAAO,CAAC,IAAI,CAACF,UAAU;YAC9C,EAAE,OAAOG,OAAO;gBACdC,QAAQC,IAAI,CAAC,oBAAoBF;gBACjC,OAAO;YACT;QACF;QAEA,SAAS;QACT,OAAO,IAAI,CAACG,OAAO,CAACrB,QAAQ;IAC9B;IAEA;;GAEC,GACDU,SAASC,KAAa,EAAQ;QAC5B,IAAI,CAACU,OAAO,CAACX,QAAQ,CAACC;IACxB;IAEA;;GAEC,GACD,MAAMW,cAAcX,KAAa,EAAoB;QACnD,IAAI,IAAI,CAACY,eAAe,EAAE;YACxB,IAAI;gBACF,OAAO,MAAMP,QAAQC,OAAO,CAAC,IAAI,CAACM,eAAe,CAACZ;YACpD,EAAE,OAAOO,OAAO;gBACdC,QAAQC,IAAI,CAAC,oBAAoBF;gBACjC,OAAO;YACT;QACF;QAEA,yBAAyB;QACzB,MAAMM,cAAc,IAAI,CAACH,OAAO,CAACrB,QAAQ;QACzC,OAAOwB,gBAAgB,QAAQA,gBAAgBb;IACjD;IAEA;;GAEC,GACDE,aAAmB;QACjB,IAAI,CAACQ,OAAO,CAACR,UAAU;IACzB;IAEA;;GAEC,GACDY,gBAAwB;QACtB,OAAO,IAAI,CAACC,UAAU;IACxB;IAtEA,YAAYC,MAMX,CAAE;QAZH,uBAAQN,WAAR,KAAA;QACA,uBAAQK,cAAR,KAAA;QACA,uBAAQlB,cAAR,KAAA;QACA,uBAAQO,cAAR,KAAA;QACA,uBAAQQ,mBAAR,KAAA;QASE,IAAI,CAACG,UAAU,GAAGC,QAAQD,cAAc;QACxC,IAAI,CAAClB,UAAU,GAAGmB,QAAQnB,cAAc;QACxC,IAAI,CAACa,OAAO,GAAGM,QAAQN,WAAY,CAAA,OAAOpB,aAAa,cACnD,IAAIF,mBAAmB,IAAI,CAACS,UAAU,IACtC,IAAIM,oBAAmB;QAC3B,IAAI,CAACC,UAAU,GAAGY,QAAQ3B;QAC1B,IAAI,CAACuB,eAAe,GAAGI,QAAQL;IACjC;AAyDF;AAEA;;CAEC,GACD,IAAIM,oBAA6C;AAK1C,SAAS9B,gBAAgB6B,MAM/B;IACCC,oBAAoB,IAAIhC,iBAAiB+B;IACzC,OAAOC;AACT;AAKO,SAAS/B;IACd,OAAO+B;AACT"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSRF 防护工具
|
|
3
|
+
* 提供 CSRF Token 的生成、存储和验证功能
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* CSRF Token 存储接口
|
|
7
|
+
*/
|
|
8
|
+
export interface CSRFTokenStorage {
|
|
9
|
+
/**
|
|
10
|
+
* 获取 Token
|
|
11
|
+
*/
|
|
12
|
+
getToken(): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* 设置 Token
|
|
15
|
+
*/
|
|
16
|
+
setToken(token: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* 清除 Token
|
|
19
|
+
*/
|
|
20
|
+
clearToken(): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* CSRF Token 管理器
|
|
24
|
+
*/
|
|
25
|
+
export declare class CSRFTokenManager {
|
|
26
|
+
private storage;
|
|
27
|
+
private headerName;
|
|
28
|
+
private cookieName;
|
|
29
|
+
private getTokenFn?;
|
|
30
|
+
private validateTokenFn?;
|
|
31
|
+
constructor(config?: {
|
|
32
|
+
storage?: CSRFTokenStorage;
|
|
33
|
+
headerName?: string;
|
|
34
|
+
cookieName?: string;
|
|
35
|
+
getToken?: () => string | Promise<string>;
|
|
36
|
+
validateToken?: (token: string) => boolean | Promise<boolean>;
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* 获取 CSRF Token
|
|
40
|
+
*/
|
|
41
|
+
getToken(): Promise<string | null>;
|
|
42
|
+
/**
|
|
43
|
+
* 设置 CSRF Token
|
|
44
|
+
*/
|
|
45
|
+
setToken(token: string): void;
|
|
46
|
+
/**
|
|
47
|
+
* 验证 CSRF Token
|
|
48
|
+
*/
|
|
49
|
+
validateToken(token: string): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* 清除 CSRF Token
|
|
52
|
+
*/
|
|
53
|
+
clearToken(): void;
|
|
54
|
+
/**
|
|
55
|
+
* 获取请求头名称
|
|
56
|
+
*/
|
|
57
|
+
getHeaderName(): string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 初始化 CSRF Token 管理器
|
|
61
|
+
*/
|
|
62
|
+
export declare function initCSRFManager(config?: {
|
|
63
|
+
storage?: CSRFTokenStorage;
|
|
64
|
+
headerName?: string;
|
|
65
|
+
cookieName?: string;
|
|
66
|
+
getToken?: () => string | Promise<string>;
|
|
67
|
+
validateToken?: (token: string) => boolean | Promise<boolean>;
|
|
68
|
+
}): CSRFTokenManager;
|
|
69
|
+
/**
|
|
70
|
+
* 获取全局 CSRF Token 管理器
|
|
71
|
+
*/
|
|
72
|
+
export declare function getCSRFManager(): CSRFTokenManager | null;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSRF 防护工具
|
|
3
|
+
* 提供 CSRF Token 的生成、存储和验证功能
|
|
4
|
+
*/ /**
|
|
5
|
+
* CSRF Token 存储接口
|
|
6
|
+
*/ function _define_property(obj, key, value) {
|
|
7
|
+
if (key in obj) {
|
|
8
|
+
Object.defineProperty(obj, key, {
|
|
9
|
+
value: value,
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
writable: true
|
|
13
|
+
});
|
|
14
|
+
} else {
|
|
15
|
+
obj[key] = value;
|
|
16
|
+
}
|
|
17
|
+
return obj;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 默认 Token 存储(使用 Cookie)
|
|
21
|
+
*/ let CookieTokenStorage = class CookieTokenStorage {
|
|
22
|
+
getToken() {
|
|
23
|
+
if (typeof document === 'undefined') {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const cookies = document.cookie.split(';');
|
|
27
|
+
for (const cookie of cookies){
|
|
28
|
+
const [name, value] = cookie.trim().split('=');
|
|
29
|
+
if (name === this.cookieName) {
|
|
30
|
+
return decodeURIComponent(value);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
setToken(token) {
|
|
36
|
+
if (typeof document === 'undefined') {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// 设置 Cookie(HttpOnly 由服务端设置,这里只设置客户端可访问的)
|
|
40
|
+
document.cookie = `${this.cookieName}=${encodeURIComponent(token)}; path=/; SameSite=Strict`;
|
|
41
|
+
}
|
|
42
|
+
clearToken() {
|
|
43
|
+
if (typeof document === 'undefined') {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
document.cookie = `${this.cookieName}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
47
|
+
}
|
|
48
|
+
constructor(cookieName = 'csrf-token'){
|
|
49
|
+
_define_property(this, "cookieName", void 0);
|
|
50
|
+
this.cookieName = cookieName;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* 内存 Token 存储(用于 SSR 或测试)
|
|
55
|
+
*/ let MemoryTokenStorage = class MemoryTokenStorage {
|
|
56
|
+
getToken() {
|
|
57
|
+
return this.token;
|
|
58
|
+
}
|
|
59
|
+
setToken(token) {
|
|
60
|
+
this.token = token;
|
|
61
|
+
}
|
|
62
|
+
clearToken() {
|
|
63
|
+
this.token = null;
|
|
64
|
+
}
|
|
65
|
+
constructor(){
|
|
66
|
+
_define_property(this, "token", null);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* CSRF Token 管理器
|
|
71
|
+
*/ export class CSRFTokenManager {
|
|
72
|
+
/**
|
|
73
|
+
* 获取 CSRF Token
|
|
74
|
+
*/ async getToken() {
|
|
75
|
+
if (this.getTokenFn) {
|
|
76
|
+
try {
|
|
77
|
+
return await Promise.resolve(this.getTokenFn());
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.warn('CSRF Token 获取失败:', error);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// 从存储中获取
|
|
84
|
+
return this.storage.getToken();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 设置 CSRF Token
|
|
88
|
+
*/ setToken(token) {
|
|
89
|
+
this.storage.setToken(token);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 验证 CSRF Token
|
|
93
|
+
*/ async validateToken(token) {
|
|
94
|
+
if (this.validateTokenFn) {
|
|
95
|
+
try {
|
|
96
|
+
return await Promise.resolve(this.validateTokenFn(token));
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.warn('CSRF Token 验证失败:', error);
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 默认验证:检查存储中的 Token 是否匹配
|
|
103
|
+
const storedToken = this.storage.getToken();
|
|
104
|
+
return storedToken !== null && storedToken === token;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 清除 CSRF Token
|
|
108
|
+
*/ clearToken() {
|
|
109
|
+
this.storage.clearToken();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 获取请求头名称
|
|
113
|
+
*/ getHeaderName() {
|
|
114
|
+
return this.headerName;
|
|
115
|
+
}
|
|
116
|
+
constructor(config){
|
|
117
|
+
_define_property(this, "storage", void 0);
|
|
118
|
+
_define_property(this, "headerName", void 0);
|
|
119
|
+
_define_property(this, "cookieName", void 0);
|
|
120
|
+
_define_property(this, "getTokenFn", void 0);
|
|
121
|
+
_define_property(this, "validateTokenFn", void 0);
|
|
122
|
+
this.headerName = config?.headerName ?? 'X-CSRF-Token';
|
|
123
|
+
this.cookieName = config?.cookieName ?? 'csrf-token';
|
|
124
|
+
this.storage = config?.storage ?? (typeof document !== 'undefined' ? new CookieTokenStorage(this.cookieName) : new MemoryTokenStorage());
|
|
125
|
+
this.getTokenFn = config?.getToken;
|
|
126
|
+
this.validateTokenFn = config?.validateToken;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 全局 CSRF Token 管理器实例
|
|
131
|
+
*/ let globalCSRFManager = null;
|
|
132
|
+
/**
|
|
133
|
+
* 初始化 CSRF Token 管理器
|
|
134
|
+
*/ export function initCSRFManager(config) {
|
|
135
|
+
globalCSRFManager = new CSRFTokenManager(config);
|
|
136
|
+
return globalCSRFManager;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* 获取全局 CSRF Token 管理器
|
|
140
|
+
*/ export function getCSRFManager() {
|
|
141
|
+
return globalCSRFManager;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * CSRF 防护工具\n * 提供 CSRF Token 的生成、存储和验证功能\n */\n\n/**\n * CSRF Token 存储接口\n */\nexport interface CSRFTokenStorage {\n /**\n * 获取 Token\n */\n getToken(): string | null;\n /**\n * 设置 Token\n */\n setToken(token: string): void;\n /**\n * 清除 Token\n */\n clearToken(): void;\n}\n\n/**\n * 默认 Token 存储(使用 Cookie)\n */\nclass CookieTokenStorage implements CSRFTokenStorage {\n private cookieName: string;\n\n constructor(cookieName: string = 'csrf-token') {\n this.cookieName = cookieName;\n }\n\n getToken(): string | null {\n if (typeof document === 'undefined') {\n return null;\n }\n\n const cookies = document.cookie.split(';');\n for (const cookie of cookies) {\n const [name, value] = cookie.trim().split('=');\n if (name === this.cookieName) {\n return decodeURIComponent(value);\n }\n }\n return null;\n }\n\n setToken(token: string): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n // 设置 Cookie(HttpOnly 由服务端设置,这里只设置客户端可访问的)\n document.cookie = `${this.cookieName}=${encodeURIComponent(token)}; path=/; SameSite=Strict`;\n }\n\n clearToken(): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n document.cookie = `${this.cookieName}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;\n }\n}\n\n/**\n * 内存 Token 存储(用于 SSR 或测试)\n */\nclass MemoryTokenStorage implements CSRFTokenStorage {\n private token: string | null = null;\n\n getToken(): string | null {\n return this.token;\n }\n\n setToken(token: string): void {\n this.token = token;\n }\n\n clearToken(): void {\n this.token = null;\n }\n}\n\n/**\n * CSRF Token 管理器\n */\nexport class CSRFTokenManager {\n private storage: CSRFTokenStorage;\n private headerName: string;\n private cookieName: string;\n private getTokenFn?: () => string | Promise<string>;\n private validateTokenFn?: (token: string) => boolean | Promise<boolean>;\n\n constructor(config?: {\n storage?: CSRFTokenStorage;\n headerName?: string;\n cookieName?: string;\n getToken?: () => string | Promise<string>;\n validateToken?: (token: string) => boolean | Promise<boolean>;\n }) {\n this.headerName = config?.headerName ?? 'X-CSRF-Token';\n this.cookieName = config?.cookieName ?? 'csrf-token';\n this.storage = config?.storage ?? (typeof document !== 'undefined' \n ? new CookieTokenStorage(this.cookieName)\n : new MemoryTokenStorage());\n this.getTokenFn = config?.getToken;\n this.validateTokenFn = config?.validateToken;\n }\n\n /**\n * 获取 CSRF Token\n */\n async getToken(): Promise<string | null> {\n if (this.getTokenFn) {\n try {\n return await Promise.resolve(this.getTokenFn());\n } catch (error) {\n console.warn('CSRF Token 获取失败:', error);\n return null;\n }\n }\n\n // 从存储中获取\n return this.storage.getToken();\n }\n\n /**\n * 设置 CSRF Token\n */\n setToken(token: string): void {\n this.storage.setToken(token);\n }\n\n /**\n * 验证 CSRF Token\n */\n async validateToken(token: string): Promise<boolean> {\n if (this.validateTokenFn) {\n try {\n return await Promise.resolve(this.validateTokenFn(token));\n } catch (error) {\n console.warn('CSRF Token 验证失败:', error);\n return false;\n }\n }\n\n // 默认验证:检查存储中的 Token 是否匹配\n const storedToken = this.storage.getToken();\n return storedToken !== null && storedToken === token;\n }\n\n /**\n * 清除 CSRF Token\n */\n clearToken(): void {\n this.storage.clearToken();\n }\n\n /**\n * 获取请求头名称\n */\n getHeaderName(): string {\n return this.headerName;\n }\n}\n\n/**\n * 全局 CSRF Token 管理器实例\n */\nlet globalCSRFManager: CSRFTokenManager | null = null;\n\n/**\n * 初始化 CSRF Token 管理器\n */\nexport function initCSRFManager(config?: {\n storage?: CSRFTokenStorage;\n headerName?: string;\n cookieName?: string;\n getToken?: () => string | Promise<string>;\n validateToken?: (token: string) => boolean | Promise<boolean>;\n}): CSRFTokenManager {\n globalCSRFManager = new CSRFTokenManager(config);\n return globalCSRFManager;\n}\n\n/**\n * 获取全局 CSRF Token 管理器\n */\nexport function getCSRFManager(): CSRFTokenManager | null {\n return globalCSRFManager;\n}\n"],"names":["CookieTokenStorage","getToken","document","cookies","cookie","split","name","value","trim","cookieName","decodeURIComponent","setToken","token","encodeURIComponent","clearToken","MemoryTokenStorage","CSRFTokenManager","getTokenFn","Promise","resolve","error","console","warn","storage","validateToken","validateTokenFn","storedToken","getHeaderName","headerName","config","globalCSRFManager","initCSRFManager","getCSRFManager"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vlian/csrf",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "CSRF token manager for vlian ecosystem",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"typesVersions": {
|
|
18
|
+
"*": {
|
|
19
|
+
"*": [
|
|
20
|
+
"dist/*.d.ts"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "npm run clean && npm run build:types && npm run build:esm && npm run build:cjs",
|
|
30
|
+
"build:types": "tsc --emitDeclarationOnly --declarationMap false --sourceMap false",
|
|
31
|
+
"build:esm": "swc src -d dist --strip-leading-paths --config-file .swcrc",
|
|
32
|
+
"build:cjs": "swc src -d dist-temp --strip-leading-paths --config-file .swcrc.cjs && node scripts/rename-cjs.js && rm -rf dist-temp",
|
|
33
|
+
"clean": "rm -rf dist dist-temp",
|
|
34
|
+
"prepublishOnly": "npm run build && npm version patch --no-git-tag-version"
|
|
35
|
+
},
|
|
36
|
+
"author": "Secra Framework Contributors",
|
|
37
|
+
"license": "Apache-2.0",
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=16.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@swc/cli": "^0.8.0",
|
|
43
|
+
"@swc/core": "^1.15.18",
|
|
44
|
+
"@types/node": "^20.0.0",
|
|
45
|
+
"typescript": "^5.9.3"
|
|
46
|
+
},
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
},
|
|
50
|
+
"packageManager": "pnpm@10.27.0"
|
|
51
|
+
}
|