@gangdai/fingerprint 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/LICENSE +21 -0
- package/README.md +223 -0
- package/dist/index.d.mts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +703 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +695 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gang.dai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# @gangdai/fingerprint
|
|
2
|
+
|
|
3
|
+
A lightweight, zero-dependency browser fingerprint collection library with full TypeScript support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔒 **High-precision fingerprinting**: Combines multiple dimensions to generate unique device identifiers
|
|
8
|
+
- 💾 **Smart caching**: Dual-layer caching with IndexedDB + LocalStorage, 30-day validity
|
|
9
|
+
- 🚀 **Lightweight & efficient**: Zero dependencies, small bundle size, excellent performance
|
|
10
|
+
- 📦 **Ready to use**: Simple API with full TypeScript support
|
|
11
|
+
- 🔄 **Fallback mechanism**: Automatically generates UUID when collection fails
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Using pnpm (recommended)
|
|
17
|
+
pnpm add @gangdai/fingerprint
|
|
18
|
+
|
|
19
|
+
# Using npm
|
|
20
|
+
npm install @gangdai/fingerprint
|
|
21
|
+
|
|
22
|
+
# Using yarn
|
|
23
|
+
yarn add @gangdai/fingerprint
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### Basic Usage
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import { getDeviceFingerprint } from '@gangdai/fingerprint';
|
|
32
|
+
|
|
33
|
+
// Get device fingerprint
|
|
34
|
+
const result = await getDeviceFingerprint();
|
|
35
|
+
console.log(result.fingerprint); // "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
|
|
36
|
+
console.log(result.isFallback); // false
|
|
37
|
+
console.log(result.timestamp); // 1705824000000
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Get Fingerprint String Only
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { getFingerprint } from '@gangdai/fingerprint';
|
|
44
|
+
|
|
45
|
+
const fingerprint = await getFingerprint();
|
|
46
|
+
console.log(fingerprint); // "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Custom Configuration
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { initFingerprint, getDeviceFingerprint } from '@gangdai/fingerprint';
|
|
53
|
+
|
|
54
|
+
// Initialize with custom config
|
|
55
|
+
initFingerprint({
|
|
56
|
+
cacheExpiry: 7 * 24 * 60 * 60 * 1000, // Cache for 7 days
|
|
57
|
+
enableIndexedDB: true, // Enable IndexedDB
|
|
58
|
+
storageKeyPrefix: 'myapp', // Custom storage key prefix
|
|
59
|
+
version: 1, // Version number
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Use configured instance
|
|
63
|
+
const result = await getDeviceFingerprint();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Use in HTTP Requests
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { getFingerprint, HTTP_HEADER_NAME } from '@gangdai/fingerprint';
|
|
70
|
+
import axios from 'axios';
|
|
71
|
+
|
|
72
|
+
// Get fingerprint
|
|
73
|
+
const fingerprint = await getFingerprint();
|
|
74
|
+
|
|
75
|
+
// Include fingerprint in request headers
|
|
76
|
+
axios.post('/api/login', data, {
|
|
77
|
+
headers: {
|
|
78
|
+
[HTTP_HEADER_NAME]: fingerprint, // 'X-Device-Fingerprint'
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Refresh and Clear
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { refreshFingerprint, clearFingerprint } from '@gangdai/fingerprint';
|
|
87
|
+
|
|
88
|
+
// Force refresh fingerprint (re-collect)
|
|
89
|
+
const newResult = await refreshFingerprint();
|
|
90
|
+
|
|
91
|
+
// Clear cached fingerprint
|
|
92
|
+
await clearFingerprint();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## API 文档
|
|
96
|
+
|
|
97
|
+
### `getDeviceFingerprint(): Promise<FingerprintResult>`
|
|
98
|
+
|
|
99
|
+
获取完整的设备指纹信息。
|
|
100
|
+
|
|
101
|
+
**返回值:**
|
|
102
|
+
```typescript
|
|
103
|
+
interface FingerprintResult {
|
|
104
|
+
fingerprint: string; // 32位 MD5 哈希值
|
|
105
|
+
isFallback: boolean; // 是否为兜底 UUID
|
|
106
|
+
timestamp: number; // 采集时间戳
|
|
107
|
+
expiresAt: number; // 过期时间戳
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `getFingerprint(): Promise<string>`
|
|
112
|
+
|
|
113
|
+
获取设备指纹字符串(简化版)。
|
|
114
|
+
|
|
115
|
+
**返回值:** 32位 MD5 哈希字符串
|
|
116
|
+
|
|
117
|
+
### `initFingerprint(config?: FingerprintConfig): void`
|
|
118
|
+
|
|
119
|
+
初始化指纹模块配置(可选)。
|
|
120
|
+
|
|
121
|
+
**参数:**
|
|
122
|
+
```typescript
|
|
123
|
+
interface FingerprintConfig {
|
|
124
|
+
cacheExpiry?: number; // 缓存过期时间(毫秒),默认 30 天
|
|
125
|
+
enableIndexedDB?: boolean; // 是否启用 IndexedDB,默认 true
|
|
126
|
+
storageKeyPrefix?: string; // 存储键名前缀,默认 'df'
|
|
127
|
+
version?: number; // 版本号,默认 1
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### `refreshFingerprint(): Promise<FingerprintResult>`
|
|
132
|
+
|
|
133
|
+
强制刷新指纹(重新采集,忽略缓存)。
|
|
134
|
+
|
|
135
|
+
### `clearFingerprint(): Promise<void>`
|
|
136
|
+
|
|
137
|
+
清除缓存的指纹数据。
|
|
138
|
+
|
|
139
|
+
### `getHeaderName(): string`
|
|
140
|
+
|
|
141
|
+
获取 HTTP Header 名称。
|
|
142
|
+
|
|
143
|
+
**返回值:** `'X-Device-Fingerprint'`
|
|
144
|
+
|
|
145
|
+
### 常量
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
import { HTTP_HEADER_NAME } from '@gangdai/fingerprint';
|
|
149
|
+
|
|
150
|
+
console.log(HTTP_HEADER_NAME); // 'X-Device-Fingerprint'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Collection Dimensions
|
|
154
|
+
|
|
155
|
+
The fingerprint collection includes the following dimensions:
|
|
156
|
+
|
|
157
|
+
- **Basic Information**: User Agent, language, timezone, screen resolution, color depth
|
|
158
|
+
- **Canvas Fingerprint**: Canvas rendering characteristics
|
|
159
|
+
- **WebGL Fingerprint**: WebGL renderer information
|
|
160
|
+
- **Audio Fingerprint**: Audio context characteristics
|
|
161
|
+
- **Font Detection**: System installed fonts list
|
|
162
|
+
- **Plugin Information**: Browser plugins list
|
|
163
|
+
- **Hardware Information**: CPU cores, memory size, touch support
|
|
164
|
+
|
|
165
|
+
## Caching Strategy
|
|
166
|
+
|
|
167
|
+
1. **Prioritize IndexedDB**: Persistent storage, unaffected by private mode
|
|
168
|
+
2. **Fallback to LocalStorage**: Alternative when IndexedDB is unavailable
|
|
169
|
+
3. **30-day validity**: Default cache for 30 days, customizable
|
|
170
|
+
4. **Version management**: Supports version numbers for future upgrades
|
|
171
|
+
|
|
172
|
+
## Fallback Mechanism
|
|
173
|
+
|
|
174
|
+
When fingerprint collection fails (e.g., private mode, permission restrictions), a UUID is automatically generated as a fallback identifier:
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
const result = await getDeviceFingerprint();
|
|
178
|
+
if (result.isFallback) {
|
|
179
|
+
console.log('Using fallback UUID:', result.fingerprint);
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## TypeScript Support
|
|
184
|
+
|
|
185
|
+
Complete TypeScript type definitions:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import type {
|
|
189
|
+
FingerprintResult,
|
|
190
|
+
FingerprintConfig,
|
|
191
|
+
CollectorResult,
|
|
192
|
+
CachedFingerprint
|
|
193
|
+
} from '@gangdai/fingerprint';
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Browser Compatibility
|
|
197
|
+
|
|
198
|
+
- Chrome 60+
|
|
199
|
+
- Firefox 55+
|
|
200
|
+
- Safari 11+
|
|
201
|
+
- Edge 79+
|
|
202
|
+
|
|
203
|
+
## Important Notes
|
|
204
|
+
|
|
205
|
+
1. **Privacy Compliance**: Ensure compliance with local privacy regulations (e.g., GDPR, CCPA) before use
|
|
206
|
+
2. **User Notification**: Recommend explaining the use of device fingerprinting in your privacy policy
|
|
207
|
+
3. **Not a Sole Identifier**: Recommend using in combination with other authentication methods
|
|
208
|
+
4. **Cache Clearing**: Users clearing browser data will cause fingerprint regeneration
|
|
209
|
+
|
|
210
|
+
## Use Cases
|
|
211
|
+
|
|
212
|
+
- 🔐 **Login Security**: Detect abnormal login behavior
|
|
213
|
+
- 🛡️ **Risk Control**: Identify malicious devices and fraudulent activities
|
|
214
|
+
- 📊 **User Analytics**: Count unique devices
|
|
215
|
+
- 🔄 **Session Management**: Cross-tab session correlation
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT License
|
|
220
|
+
|
|
221
|
+
## Support
|
|
222
|
+
|
|
223
|
+
For issues or suggestions, please visit [GitHub Issues](https://github.com/gangdai/fingerprint/issues).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 设备指纹模块 - 类型定义
|
|
3
|
+
* @description 独立模块,便于其他系统复用
|
|
4
|
+
*/
|
|
5
|
+
/** 指纹采集结果 */
|
|
6
|
+
interface FingerprintResult {
|
|
7
|
+
/** 指纹哈希值 (32位MD5) */
|
|
8
|
+
fingerprint: string;
|
|
9
|
+
/** 是否为兜底UUID */
|
|
10
|
+
isFallback: boolean;
|
|
11
|
+
/** 采集时间戳 */
|
|
12
|
+
timestamp: number;
|
|
13
|
+
/** 过期时间戳 */
|
|
14
|
+
expiresAt: number;
|
|
15
|
+
}
|
|
16
|
+
/** 指纹管理器配置 */
|
|
17
|
+
interface FingerprintConfig {
|
|
18
|
+
/** 缓存过期时间(毫秒),默认30天 */
|
|
19
|
+
cacheExpiry?: number;
|
|
20
|
+
/** 是否启用IndexedDB,默认true */
|
|
21
|
+
enableIndexedDB?: boolean;
|
|
22
|
+
/** 存储键名前缀 */
|
|
23
|
+
storageKeyPrefix?: string;
|
|
24
|
+
/** 当前版本号 */
|
|
25
|
+
version?: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** HTTP Header 名称 */
|
|
29
|
+
declare const HTTP_HEADER_NAME = "X-Device-Fingerprint";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 设备指纹模块 - 主入口
|
|
33
|
+
*
|
|
34
|
+
* @description
|
|
35
|
+
* 独立、高内聚的设备指纹模块,便于复用到其他系统。
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { getDeviceFingerprint, initFingerprint } from 'src/utils/fingerprint';
|
|
40
|
+
*
|
|
41
|
+
* // 方式1: 使用默认配置
|
|
42
|
+
* const fp = await getDeviceFingerprint();
|
|
43
|
+
* console.log(fp.fingerprint); // 32位MD5哈希
|
|
44
|
+
*
|
|
45
|
+
* // 方式2: 自定义配置
|
|
46
|
+
* initFingerprint({
|
|
47
|
+
* cacheExpiry: 7 * 24 * 60 * 60 * 1000, // 7天
|
|
48
|
+
* storageKeyPrefix: 'myapp',
|
|
49
|
+
* });
|
|
50
|
+
* const fp2 = await getDeviceFingerprint();
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @author IDaaS Team
|
|
54
|
+
* @version 1.0.0
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 初始化指纹模块(可选)
|
|
59
|
+
* @param config 配置选项
|
|
60
|
+
*/
|
|
61
|
+
declare function initFingerprint(config?: FingerprintConfig): void;
|
|
62
|
+
/**
|
|
63
|
+
* 获取设备指纹
|
|
64
|
+
* @returns 指纹结果
|
|
65
|
+
*/
|
|
66
|
+
declare function getDeviceFingerprint(): Promise<FingerprintResult>;
|
|
67
|
+
/**
|
|
68
|
+
* 获取指纹值(简化版,仅返回哈希字符串)
|
|
69
|
+
* @returns 32位MD5哈希字符串
|
|
70
|
+
*/
|
|
71
|
+
declare function getFingerprint(): Promise<string>;
|
|
72
|
+
/**
|
|
73
|
+
* 强制刷新指纹
|
|
74
|
+
* @returns 新的指纹结果
|
|
75
|
+
*/
|
|
76
|
+
declare function refreshFingerprint(): Promise<FingerprintResult>;
|
|
77
|
+
/**
|
|
78
|
+
* 清除指纹缓存
|
|
79
|
+
*/
|
|
80
|
+
declare function clearFingerprint(): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* 获取HTTP Header名称
|
|
83
|
+
*/
|
|
84
|
+
declare function getHeaderName(): string;
|
|
85
|
+
|
|
86
|
+
export { type FingerprintConfig, type FingerprintResult, HTTP_HEADER_NAME, clearFingerprint, getDeviceFingerprint, getFingerprint, getHeaderName, initFingerprint, refreshFingerprint };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 设备指纹模块 - 类型定义
|
|
3
|
+
* @description 独立模块,便于其他系统复用
|
|
4
|
+
*/
|
|
5
|
+
/** 指纹采集结果 */
|
|
6
|
+
interface FingerprintResult {
|
|
7
|
+
/** 指纹哈希值 (32位MD5) */
|
|
8
|
+
fingerprint: string;
|
|
9
|
+
/** 是否为兜底UUID */
|
|
10
|
+
isFallback: boolean;
|
|
11
|
+
/** 采集时间戳 */
|
|
12
|
+
timestamp: number;
|
|
13
|
+
/** 过期时间戳 */
|
|
14
|
+
expiresAt: number;
|
|
15
|
+
}
|
|
16
|
+
/** 指纹管理器配置 */
|
|
17
|
+
interface FingerprintConfig {
|
|
18
|
+
/** 缓存过期时间(毫秒),默认30天 */
|
|
19
|
+
cacheExpiry?: number;
|
|
20
|
+
/** 是否启用IndexedDB,默认true */
|
|
21
|
+
enableIndexedDB?: boolean;
|
|
22
|
+
/** 存储键名前缀 */
|
|
23
|
+
storageKeyPrefix?: string;
|
|
24
|
+
/** 当前版本号 */
|
|
25
|
+
version?: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** HTTP Header 名称 */
|
|
29
|
+
declare const HTTP_HEADER_NAME = "X-Device-Fingerprint";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 设备指纹模块 - 主入口
|
|
33
|
+
*
|
|
34
|
+
* @description
|
|
35
|
+
* 独立、高内聚的设备指纹模块,便于复用到其他系统。
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* import { getDeviceFingerprint, initFingerprint } from 'src/utils/fingerprint';
|
|
40
|
+
*
|
|
41
|
+
* // 方式1: 使用默认配置
|
|
42
|
+
* const fp = await getDeviceFingerprint();
|
|
43
|
+
* console.log(fp.fingerprint); // 32位MD5哈希
|
|
44
|
+
*
|
|
45
|
+
* // 方式2: 自定义配置
|
|
46
|
+
* initFingerprint({
|
|
47
|
+
* cacheExpiry: 7 * 24 * 60 * 60 * 1000, // 7天
|
|
48
|
+
* storageKeyPrefix: 'myapp',
|
|
49
|
+
* });
|
|
50
|
+
* const fp2 = await getDeviceFingerprint();
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @author IDaaS Team
|
|
54
|
+
* @version 1.0.0
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 初始化指纹模块(可选)
|
|
59
|
+
* @param config 配置选项
|
|
60
|
+
*/
|
|
61
|
+
declare function initFingerprint(config?: FingerprintConfig): void;
|
|
62
|
+
/**
|
|
63
|
+
* 获取设备指纹
|
|
64
|
+
* @returns 指纹结果
|
|
65
|
+
*/
|
|
66
|
+
declare function getDeviceFingerprint(): Promise<FingerprintResult>;
|
|
67
|
+
/**
|
|
68
|
+
* 获取指纹值(简化版,仅返回哈希字符串)
|
|
69
|
+
* @returns 32位MD5哈希字符串
|
|
70
|
+
*/
|
|
71
|
+
declare function getFingerprint(): Promise<string>;
|
|
72
|
+
/**
|
|
73
|
+
* 强制刷新指纹
|
|
74
|
+
* @returns 新的指纹结果
|
|
75
|
+
*/
|
|
76
|
+
declare function refreshFingerprint(): Promise<FingerprintResult>;
|
|
77
|
+
/**
|
|
78
|
+
* 清除指纹缓存
|
|
79
|
+
*/
|
|
80
|
+
declare function clearFingerprint(): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* 获取HTTP Header名称
|
|
83
|
+
*/
|
|
84
|
+
declare function getHeaderName(): string;
|
|
85
|
+
|
|
86
|
+
export { type FingerprintConfig, type FingerprintResult, HTTP_HEADER_NAME, clearFingerprint, getDeviceFingerprint, getFingerprint, getHeaderName, initFingerprint, refreshFingerprint };
|