@gangdai/fingerprint 1.0.0 → 1.1.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 CHANGED
@@ -23,6 +23,18 @@ npm install @gangdai/fingerprint
23
23
  yarn add @gangdai/fingerprint
24
24
  ```
25
25
 
26
+ ### Browser (Script Tag)
27
+
28
+ ```html
29
+ <script src="dist/index.browser.js"></script>
30
+ <script>
31
+ // 全局变量 Fingerprint 可用
32
+ Fingerprint.getFingerprint().then(fp => {
33
+ console.log(fp);
34
+ });
35
+ </script>
36
+ ```
37
+
26
38
  ## Quick Start
27
39
 
28
40
  ### Basic Usage
@@ -121,7 +133,7 @@ interface FingerprintResult {
121
133
  **参数:**
122
134
  ```typescript
123
135
  interface FingerprintConfig {
124
- cacheExpiry?: number; // 缓存过期时间(毫秒),默认 30
136
+ cacheExpiry?: number; // 缓存过期时间(毫秒),默认 20
125
137
  enableIndexedDB?: boolean; // 是否启用 IndexedDB,默认 true
126
138
  storageKeyPrefix?: string; // 存储键名前缀,默认 'df'
127
139
  version?: number; // 版本号,默认 1
@@ -0,0 +1,2 @@
1
+ var Fingerprint=(function(exports){'use strict';var v="DEVICE_FINGERPRINT",M="DeviceFingerprintDB",G="fingerprints";var U="X-Device-Fingerprint";function d(i,n){return i+n&4294967295}function F(i,n,e,r,t,o){let s=d(d(n,i),d(r,o));return d(s<<t|s>>>32-t,e)}function c(i,n,e,r,t,o,s){return F(n&e|~n&r,i,n,t,o,s)}function l(i,n,e,r,t,o,s){return F(n&r|e&~r,i,n,t,o,s)}function u(i,n,e,r,t,o,s){return F(n^e^r,i,n,t,o,s)}function m(i,n,e,r,t,o,s){return F(e^(n|~r),i,n,t,o,s)}function V(i,n){let e=i[0],r=i[1],t=i[2],o=i[3];e=c(e,r,t,o,n[0],7,-680876936),o=c(o,e,r,t,n[1],12,-389564586),t=c(t,o,e,r,n[2],17,606105819),r=c(r,t,o,e,n[3],22,-1044525330),e=c(e,r,t,o,n[4],7,-176418897),o=c(o,e,r,t,n[5],12,1200080426),t=c(t,o,e,r,n[6],17,-1473231341),r=c(r,t,o,e,n[7],22,-45705983),e=c(e,r,t,o,n[8],7,1770035416),o=c(o,e,r,t,n[9],12,-1958414417),t=c(t,o,e,r,n[10],17,-42063),r=c(r,t,o,e,n[11],22,-1990404162),e=c(e,r,t,o,n[12],7,1804603682),o=c(o,e,r,t,n[13],12,-40341101),t=c(t,o,e,r,n[14],17,-1502002290),r=c(r,t,o,e,n[15],22,1236535329),e=l(e,r,t,o,n[1],5,-165796510),o=l(o,e,r,t,n[6],9,-1069501632),t=l(t,o,e,r,n[11],14,643717713),r=l(r,t,o,e,n[0],20,-373897302),e=l(e,r,t,o,n[5],5,-701558691),o=l(o,e,r,t,n[10],9,38016083),t=l(t,o,e,r,n[15],14,-660478335),r=l(r,t,o,e,n[4],20,-405537848),e=l(e,r,t,o,n[9],5,568446438),o=l(o,e,r,t,n[14],9,-1019803690),t=l(t,o,e,r,n[3],14,-187363961),r=l(r,t,o,e,n[8],20,1163531501),e=l(e,r,t,o,n[13],5,-1444681467),o=l(o,e,r,t,n[2],9,-51403784),t=l(t,o,e,r,n[7],14,1735328473),r=l(r,t,o,e,n[12],20,-1926607734),e=u(e,r,t,o,n[5],4,-378558),o=u(o,e,r,t,n[8],11,-2022574463),t=u(t,o,e,r,n[11],16,1839030562),r=u(r,t,o,e,n[14],23,-35309556),e=u(e,r,t,o,n[1],4,-1530992060),o=u(o,e,r,t,n[4],11,1272893353),t=u(t,o,e,r,n[7],16,-155497632),r=u(r,t,o,e,n[10],23,-1094730640),e=u(e,r,t,o,n[13],4,681279174),o=u(o,e,r,t,n[0],11,-358537222),t=u(t,o,e,r,n[3],16,-722521979),r=u(r,t,o,e,n[6],23,76029189),e=u(e,r,t,o,n[9],4,-640364487),o=u(o,e,r,t,n[12],11,-421815835),t=u(t,o,e,r,n[15],16,530742520),r=u(r,t,o,e,n[2],23,-995338651),e=m(e,r,t,o,n[0],6,-198630844),o=m(o,e,r,t,n[7],10,1126891415),t=m(t,o,e,r,n[14],15,-1416354905),r=m(r,t,o,e,n[5],21,-57434055),e=m(e,r,t,o,n[12],6,1700485571),o=m(o,e,r,t,n[3],10,-1894986606),t=m(t,o,e,r,n[10],15,-1051523),r=m(r,t,o,e,n[1],21,-2054922799),e=m(e,r,t,o,n[8],6,1873313359),o=m(o,e,r,t,n[15],10,-30611744),t=m(t,o,e,r,n[6],15,-1560198380),r=m(r,t,o,e,n[13],21,1309151649),e=m(e,r,t,o,n[4],6,-145523070),o=m(o,e,r,t,n[11],10,-1120210379),t=m(t,o,e,r,n[2],15,718787259),r=m(r,t,o,e,n[9],21,-343485551),i[0]=d(e,i[0]),i[1]=d(r,i[1]),i[2]=d(t,i[2]),i[3]=d(o,i[3]);}function K(i){let n=[];for(let e=0;e<64;e+=4)n[e>>2]=i.charCodeAt(e)+(i.charCodeAt(e+1)<<8)+(i.charCodeAt(e+2)<<16)+(i.charCodeAt(e+3)<<24);return n}function X(i){let n="0123456789abcdef",e="";for(let r=0;r<4;r++)e+=n.charAt(i>>r*8+4&15)+n.charAt(i>>r*8&15);return e}function W(i){return i.map(X).join("")}function q(i){return unescape(encodeURIComponent(i))}function O(i){let n=q(i),e=n.length,r=[1732584193,-271733879,-1732584194,271733878],t;for(t=64;t<=e;t+=64)V(r,K(n.substring(t-64,t)));let o=n.substring(t-64),s=Array(16).fill(0);for(t=0;t<o.length;t++)s[t>>2]|=o.charCodeAt(t)<<(t%4<<3);return s[t>>2]|=128<<(t%4<<3),t>55&&(V(r,s),s.fill(0)),s[14]=e*8,V(r,s),W(r)}function j(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID().replace(/-/g,""):"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".replace(/x/g,()=>Math.floor(Math.random()*16).toString(16))}var C=class{constructor(){this.name="canvas";}isKnownNoisyBrowser(){let e=navigator.userAgent.match(/Version\/(\d+).*Safari/);return !!(e&&parseInt(e[1],10)>=17)}async collect(n){try{if(this.isKnownNoisyBrowser())return {name:this.name,value:"",success:!1,error:"Browser known for canvas anti-fingerprinting"};let e=document.createElement("canvas"),r=e.getContext("2d");if(!r)return {name:this.name,value:"",success:!1,error:"Canvas context not available"};e.width=200,e.height=50,r.fillStyle="#f60",r.fillRect(0,0,200,50),r.fillStyle="#069",r.font="14px Arial",r.fillText("Device Fingerprint Canvas",2,15),r.fillStyle="rgba(102, 204, 0, 0.7)",r.font="18px Times New Roman",r.fillText("!@#$%^&*()_+-=[]{}|;:",4,35),r.beginPath(),r.arc(150,25,20,0,Math.PI*2,!0),r.closePath(),r.fillStyle="#ff0",r.fill(),r.shadowBlur=10,r.shadowColor="blue",r.fillRect(160,10,30,30);let t=e.toDataURL("image/png"),o=e.toDataURL("image/png");return t!==o?{name:this.name,value:"",success:!1,error:"Canvas noise detected (unstable)"}:{name:this.name,value:t,success:!0}}catch(e){return {name:this.name,value:"",success:false,error:e instanceof Error?e.message:"Unknown error"}}}};var w=class{constructor(){this.name="webgl";}async collect(n){try{let e=document.createElement("canvas"),r=e.getContext("webgl")||e.getContext("experimental-webgl");if(!r)return {name:this.name,value:"",success:!1,error:"WebGL not available"};let t=r,o=t.getExtension("WEBGL_debug_renderer_info"),s=[];if(o){let p=t.getParameter(o.UNMASKED_VENDOR_WEBGL),g=t.getParameter(o.UNMASKED_RENDERER_WEBGL);s.push(`vendor:${p}`),s.push(`renderer:${g}`);}s.push(`version:${t.getParameter(t.VERSION)}`),s.push(`shadingLanguageVersion:${t.getParameter(t.SHADING_LANGUAGE_VERSION)}`),s.push(`maxTextureSize:${t.getParameter(t.MAX_TEXTURE_SIZE)}`),s.push(`maxRenderbufferSize:${t.getParameter(t.MAX_RENDERBUFFER_SIZE)}`),s.push(`maxViewportDims:${t.getParameter(t.MAX_VIEWPORT_DIMS)}`),s.push(`maxVertexAttribs:${t.getParameter(t.MAX_VERTEX_ATTRIBS)}`),s.push(`maxVertexUniformVectors:${t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS)}`),s.push(`maxFragmentUniformVectors:${t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS)}`);let f=t.getSupportedExtensions()||[];return s.push(`extensions:${f.sort().join(",")}`),{name:this.name,value:s.join("|"),success:!0}}catch(e){return {name:this.name,value:"",success:false,error:e instanceof Error?e.message:"Unknown error"}}}};var y=class{constructor(){this.name="audio";}isKnownNoisyBrowser(){let n=navigator.userAgent,e=n.match(/Version\/(\d+).*Safari/);if(e&&parseInt(e[1],10)>=17)return true;let r=n.match(/SamsungBrowser\/(\d+)/);return !!(r&&parseInt(r[1],10)>=26)}async collect(n){try{if(this.isKnownNoisyBrowser())return {name:this.name,value:"",success:!1,error:"Browser known for audio anti-fingerprinting"};let e=window.OfflineAudioContext||window.webkitOfflineAudioContext;if(!e)return {name:this.name,value:"",success:!1,error:"OfflineAudioContext not available"};let r=44100,o=r*.5,s=new e(1,o,r),f=s.createOscillator();f.type="triangle",f.frequency.setValueAtTime(1e4,s.currentTime);let p=s.createDynamicsCompressor();p.threshold.setValueAtTime(-50,s.currentTime),p.knee.setValueAtTime(40,s.currentTime),p.ratio.setValueAtTime(12,s.currentTime),p.attack.setValueAtTime(0,s.currentTime),p.release.setValueAtTime(.25,s.currentTime),f.connect(p),p.connect(s.destination),f.start(0);let b=(await s.startRendering()).getChannelData(0),a=[],N=[4500,5e3,5500,6e3,6500,7e3,7500,8e3,8500,9e3,9500,1e4,10500,11e3,11500,12e3,12500,13e3,13500,14e3];for(let h of N)h<b.length&&a.push(b[h]);let A=a.reduce((h,B)=>h+B,0)/a.length,$=a.reduce((h,B)=>h+Math.pow(B-A,2),0)/a.length,H=[...a.map(h=>h.toFixed(8)),`avg:${A.toFixed(8)}`,`var:${$.toFixed(8)}`].join(",");return {name:this.name,value:H,success:!0}}catch(e){return {name:this.name,value:"",success:false,error:e instanceof Error?e.message:"Unknown error"}}}};var E=class{constructor(){this.name="screen";}isSafari17Plus(){let e=navigator.userAgent.match(/Version\/(\d+).*Safari/);return !!(e&&parseInt(e[1],10)>=17)}async collect(n){try{let e=[];this.isSafari17Plus()||(e.push(`width:${screen.width}`),e.push(`height:${screen.height}`),e.push(`availWidth:${screen.availWidth}`),e.push(`availHeight:${screen.availHeight}`)),e.push(`colorDepth:${screen.colorDepth}`),e.push(`pixelDepth:${screen.pixelDepth}`),e.push(`devicePixelRatio:${window.devicePixelRatio||1}`),screen.orientation&&e.push(`orientation:${screen.orientation.type}`);let t=navigator.maxTouchPoints||0;return e.push(`maxTouchPoints:${t}`),e.push(`touchSupport:${t>0}`),{name:this.name,value:e.join("|"),success:!0}}catch(e){return {name:this.name,value:"",success:false,error:e instanceof Error?e.message:"Unknown error"}}}};var R=class{constructor(){this.name="system";}async collect(n){try{let e=[];n?.strictBrowserMode&&e.push(`userAgent:${navigator.userAgent}`),e.push(`timezone:${Intl.DateTimeFormat().resolvedOptions().timeZone}`),e.push(`timezoneOffset:${new Date().getTimezoneOffset()}`),e.push(`language:${navigator.language}`),e.push(`hardwareConcurrency:${navigator.hardwareConcurrency||"unknown"}`);let r=navigator.deviceMemory;r&&e.push(`deviceMemory:${r}`),e.push(`platform:${navigator.platform}`),e.push(`cookieEnabled:${navigator.cookieEnabled}`),e.push(`javaEnabled:${typeof navigator.javaEnabled=="function"?navigator.javaEnabled():!1}`);let t=navigator.doNotTrack||window.doNotTrack;return e.push(`doNotTrack:${t||"unknown"}`),e.push(`pdfViewerEnabled:${navigator.pdfViewerEnabled??"unknown"}`),e.push(`webdriver:${navigator.webdriver||!1}`),{name:this.name,value:e.join("|"),success:!0}}catch(e){return {name:this.name,value:"",success:false,error:e instanceof Error?e.message:"Unknown error"}}}};function L(){return [new C,new w,new y,new E,new R]}var S=class{constructor(n){this.key=n?`${n}_${v}`:v;}async get(){try{let n=localStorage.getItem(this.key);return n?JSON.parse(n):null}catch{return null}}async set(n){try{localStorage.setItem(this.key,JSON.stringify(n));}catch(e){console.warn("[Fingerprint] Failed to save to localStorage:",e);}}async clear(){try{localStorage.removeItem(this.key);}catch{}}};var P=class{constructor(n){this.db=null;this.dbName=n?`${n}_${M}`:M,this.storeName=G,this.key=v;}async openDB(){return this.db?this.db:new Promise((n,e)=>{let r=indexedDB.open(this.dbName,1);r.onerror=()=>{e(new Error("Failed to open IndexedDB"));},r.onsuccess=()=>{this.db=r.result,n(r.result);},r.onupgradeneeded=t=>{let o=t.target.result;o.objectStoreNames.contains(this.storeName)||o.createObjectStore(this.storeName,{keyPath:"id"});};})}async get(){try{let n=await this.openDB();return new Promise(e=>{let o=n.transaction(this.storeName,"readonly").objectStore(this.storeName).get(this.key);o.onerror=()=>{e(null);},o.onsuccess=()=>{let s=o.result;s&&s.data?e(s.data):e(null);};})}catch{return null}}async set(n){try{let e=await this.openDB();return new Promise((r,t)=>{let f=e.transaction(this.storeName,"readwrite").objectStore(this.storeName).put({id:this.key,data:n});f.onerror=()=>{t(new Error("Failed to save to IndexedDB"));},f.onsuccess=()=>{r();};})}catch(e){console.warn("[Fingerprint] Failed to save to IndexedDB:",e);}}async clear(){try{let n=await this.openDB();return new Promise(e=>{n.transaction(this.storeName,"readwrite").objectStore(this.storeName).delete(this.key),e();})}catch{}}};var D=class{constructor(n={}){this.cachedResult=null;this.config={cacheExpiry:n.cacheExpiry??63072e7,enableIndexedDB:n.enableIndexedDB??true,storageKeyPrefix:n.storageKeyPrefix??"df",version:n.version??1,strictBrowserMode:n.strictBrowserMode??false,debug:n.debug??false},this.collectors=L(),this.localStorage=new S(this.config.storageKeyPrefix),this.indexedDB=this.config.enableIndexedDB?new P(this.config.storageKeyPrefix):null;}async getFingerprint(){if(this.cachedResult&&!this.isExpired(this.cachedResult.expiresAt))return this.cachedResult;let n=await this.localStorage.get();if(n&&!this.isExpired(n.expiresAt))return this.cachedResult=this.toResult(n),this.cachedResult;if(this.indexedDB){let e=await this.indexedDB.get();if(e&&!this.isExpired(e.expiresAt))return await this.localStorage.set(e),this.cachedResult=this.toResult(e),this.cachedResult}return this.collectAndCache()}async refresh(){return this.collectAndCache()}async clear(){this.cachedResult=null,await this.localStorage.clear(),this.indexedDB&&await this.indexedDB.clear();}async collectAndCache(){let{fingerprint:n,isFallback:e,debugInfo:r}=await this.collect(),t=Date.now(),o={fingerprint:n,isFallback:e,createdAt:t,expiresAt:t+this.config.cacheExpiry,version:this.config.version};return await this.localStorage.set(o),this.indexedDB&&await this.indexedDB.set(o),this.cachedResult=this.toResult(o,r),this.cachedResult}async collect(){let n=performance.now(),e=[];this.config.debug&&(console.group("[Fingerprint] \u5F00\u59CB\u91C7\u96C6\u6307\u7EB9"),console.log("\u914D\u7F6E:",this.config),console.log("User-Agent:",navigator.userAgent));try{let r={strictBrowserMode:this.config.strictBrowserMode},o=(await Promise.all(this.collectors.map(async g=>{let b=performance.now(),a=await g.collect(r),N=performance.now()-b,x={name:a.name,success:a.success,duration:Math.round(N*100)/100,value:a.value?a.value.substring(0,200):"",valueLength:a.value?.length||0,valueHash:a.value?O(a.value):"",error:a.error};if(e.push(x),this.config.debug){let A=a.success?"\u2713":"\u2717",$=a.success?"color: #10b981":"color: #ef4444";console.log(`%c${A} ${a.name}`,$,`| \u8017\u65F6: ${x.duration}ms`,`| \u957F\u5EA6: ${x.valueLength}`,`| \u54C8\u5E0C: ${x.valueHash.substring(0,8)}...`,a.error?`| \u9519\u8BEF: ${a.error}`:""),console.log(" \u2514\u2500 \u539F\u59CB\u503C:",a.value||"(\u7A7A)");}return a}))).filter(g=>g.success&&g.value);if(o.length===0){let g=j(),b=Math.round((performance.now()-n)*100)/100;return this.config.debug&&(console.warn("[Fingerprint] \u6240\u6709\u91C7\u96C6\u5668\u5931\u8D25\uFF0C\u4F7F\u7528\u515C\u5E95 UUID:",g),console.log(`[Fingerprint] \u603B\u8017\u65F6: ${b}ms`),console.groupEnd()),{fingerprint:g,isFallback:!0,debugInfo:this.config.debug?{duration:b,collectors:e,rawData:"",userAgent:navigator.userAgent}:void 0}}let s=o.map(g=>`${g.name}:${g.value}`).sort().join("|"),f=O(s),p=Math.round((performance.now()-n)*100)/100;return this.config.debug&&(console.log("[Fingerprint] \u6210\u529F\u91C7\u96C6\u5668:",o.map(g=>g.name).join(", ")),console.log("[Fingerprint] \u539F\u59CB\u6570\u636E\u957F\u5EA6:",s.length),console.log("[Fingerprint] \u6700\u7EC8\u6307\u7EB9:",f),console.log(`[Fingerprint] \u603B\u8017\u65F6: ${p}ms`),console.groupEnd()),{fingerprint:f,isFallback:!1,debugInfo:this.config.debug?{duration:p,collectors:e,rawData:s,userAgent:navigator.userAgent}:void 0}}catch(r){let t=Math.round((performance.now()-n)*100)/100,o=j();return this.config.debug?(console.error("[Fingerprint] \u91C7\u96C6\u5F02\u5E38:",r),console.warn("[Fingerprint] \u4F7F\u7528\u515C\u5E95 UUID:",o),console.log(`[Fingerprint] \u603B\u8017\u65F6: ${t}ms`),console.groupEnd()):console.warn("[Fingerprint] Collection failed, using fallback UUID:",r),{fingerprint:o,isFallback:true,debugInfo:this.config.debug?{duration:t,collectors:e,rawData:"",userAgent:navigator.userAgent}:void 0}}}isExpired(n){return Date.now()>n}toResult(n,e){let r={fingerprint:n.fingerprint,isFallback:n.isFallback,timestamp:n.createdAt,expiresAt:n.expiresAt};return e&&(r.debug=e),r}};var T=null;function Te(i){T=new D(i);}function _(){return T||(T=new D),T}async function _e(){return _().getFingerprint()}async function Ne(){return (await _().getFingerprint()).fingerprint}async function $e(){return _().refresh()}async function Be(){return _().clear()}function Me(){return U}exports.HTTP_HEADER_NAME=U;exports.clearFingerprint=Be;exports.getDeviceFingerprint=_e;exports.getFingerprint=Ne;exports.getHeaderName=Me;exports.initFingerprint=Te;exports.refreshFingerprint=$e;return exports;})({});//# sourceMappingURL=index.browser.js.map
2
+ //# sourceMappingURL=index.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/core/hash.ts","../src/collectors/canvas.ts","../src/collectors/webgl.ts","../src/collectors/audio.ts","../src/collectors/screen.ts","../src/collectors/system.ts","../src/collectors/index.ts","../src/storage/local-storage.ts","../src/storage/indexed-db.ts","../src/core/fingerprint-manager.ts","../src/index.ts"],"names":["STORAGE_KEY","IDB_DATABASE_NAME","IDB_STORE_NAME","HTTP_HEADER_NAME","add32","a","b","cmn","q","x","s","t","sum","ff","c","d","gg","hh","ii","md5cycle","k","md5blk","md5blks","i","rhex","n","hexChr","j","hex","toUTF8","str","md5","input","state","tail","arr","generateUUID","CanvasCollector","safariMatch","_config","canvas","ctx","dataUrl1","dataUrl2","error","WebGLCollector","gl","webglContext","debugInfo","components","vendor","renderer","extensions","AudioCollector","ua","samsungMatch","OfflineAudioContextClass","sampleRate","length","context","oscillator","compressor","channelData","fingerprints","samplePoints","point","avg","variance","acc","val","value","v","ScreenCollector","maxTouchPoints","SystemCollector","config","deviceMemory","doNotTrack","createCollectors","LocalStorageAdapter","prefix","data","IndexedDBAdapter","resolve","reject","request","event","db","result","FingerprintManager","localCache","idbCache","fingerprint","isFallback","now","cached","startTime","collectorDebugInfos","collectorConfig","successResults","collector","collectorStart","collectorDuration","debugItem","status","color","r","fallbackFingerprint","totalDuration","rawData","expiresAt","manager","initFingerprint","getManager","getDeviceFingerprint","getFingerprint","refreshFingerprint","clearFingerprint","getHeaderName"],"mappings":"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","file":"index.browser.js","sourcesContent":["/**\n * 设备指纹模块 - 常量配置\n */\n\n/** 默认缓存过期时间:20年(毫秒) */\nexport const DEFAULT_CACHE_EXPIRY = 20 * 365 * 24 * 60 * 60 * 1000;\n\n/** 存储键名 */\nexport const STORAGE_KEY = 'DEVICE_FINGERPRINT';\n\n/** IndexedDB 数据库名 */\nexport const IDB_DATABASE_NAME = 'DeviceFingerprintDB';\n\n/** IndexedDB 存储表名 */\nexport const IDB_STORE_NAME = 'fingerprints';\n\n/** 当前版本号 */\nexport const CURRENT_VERSION = 1;\n\n/** HTTP Header 名称 */\nexport const HTTP_HEADER_NAME = 'X-Device-Fingerprint';\n\n/** 采集器名称枚举 */\nexport enum CollectorName {\n Canvas = 'canvas',\n WebGL = 'webgl',\n Audio = 'audio',\n Screen = 'screen',\n System = 'system',\n}\n","/**\n * 哈希计算工具\n * @description 使用MD5算法生成32位十六进制字符串\n */\n\n// MD5 辅助函数 - 定义在使用之前以避免 ESLint no-use-before-define 错误\nfunction add32(a: number, b: number): number {\n return (a + b) & 0xffffffff;\n}\n\nfunction cmn(q: number, a: number, b: number, x: number, s: number, t: number): number {\n const sum = add32(add32(a, q), add32(x, t));\n return add32((sum << s) | (sum >>> (32 - s)), b);\n}\n\nfunction ff(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {\n return cmn((b & c) | (~b & d), a, b, x, s, t);\n}\n\nfunction gg(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {\n return cmn((b & d) | (c & ~d), a, b, x, s, t);\n}\n\nfunction hh(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {\n return cmn(b ^ c ^ d, a, b, x, s, t);\n}\n\nfunction ii(a: number, b: number, c: number, d: number, x: number, s: number, t: number): number {\n return cmn(c ^ (b | ~d), a, b, x, s, t);\n}\n\nfunction md5cycle(x: number[], k: number[]): void {\n let a = x[0],\n b = x[1],\n c = x[2],\n d = x[3];\n\n a = ff(a, b, c, d, k[0], 7, -680876936);\n d = ff(d, a, b, c, k[1], 12, -389564586);\n c = ff(c, d, a, b, k[2], 17, 606105819);\n b = ff(b, c, d, a, k[3], 22, -1044525330);\n a = ff(a, b, c, d, k[4], 7, -176418897);\n d = ff(d, a, b, c, k[5], 12, 1200080426);\n c = ff(c, d, a, b, k[6], 17, -1473231341);\n b = ff(b, c, d, a, k[7], 22, -45705983);\n a = ff(a, b, c, d, k[8], 7, 1770035416);\n d = ff(d, a, b, c, k[9], 12, -1958414417);\n c = ff(c, d, a, b, k[10], 17, -42063);\n b = ff(b, c, d, a, k[11], 22, -1990404162);\n a = ff(a, b, c, d, k[12], 7, 1804603682);\n d = ff(d, a, b, c, k[13], 12, -40341101);\n c = ff(c, d, a, b, k[14], 17, -1502002290);\n b = ff(b, c, d, a, k[15], 22, 1236535329);\n\n a = gg(a, b, c, d, k[1], 5, -165796510);\n d = gg(d, a, b, c, k[6], 9, -1069501632);\n c = gg(c, d, a, b, k[11], 14, 643717713);\n b = gg(b, c, d, a, k[0], 20, -373897302);\n a = gg(a, b, c, d, k[5], 5, -701558691);\n d = gg(d, a, b, c, k[10], 9, 38016083);\n c = gg(c, d, a, b, k[15], 14, -660478335);\n b = gg(b, c, d, a, k[4], 20, -405537848);\n a = gg(a, b, c, d, k[9], 5, 568446438);\n d = gg(d, a, b, c, k[14], 9, -1019803690);\n c = gg(c, d, a, b, k[3], 14, -187363961);\n b = gg(b, c, d, a, k[8], 20, 1163531501);\n a = gg(a, b, c, d, k[13], 5, -1444681467);\n d = gg(d, a, b, c, k[2], 9, -51403784);\n c = gg(c, d, a, b, k[7], 14, 1735328473);\n b = gg(b, c, d, a, k[12], 20, -1926607734);\n\n a = hh(a, b, c, d, k[5], 4, -378558);\n d = hh(d, a, b, c, k[8], 11, -2022574463);\n c = hh(c, d, a, b, k[11], 16, 1839030562);\n b = hh(b, c, d, a, k[14], 23, -35309556);\n a = hh(a, b, c, d, k[1], 4, -1530992060);\n d = hh(d, a, b, c, k[4], 11, 1272893353);\n c = hh(c, d, a, b, k[7], 16, -155497632);\n b = hh(b, c, d, a, k[10], 23, -1094730640);\n a = hh(a, b, c, d, k[13], 4, 681279174);\n d = hh(d, a, b, c, k[0], 11, -358537222);\n c = hh(c, d, a, b, k[3], 16, -722521979);\n b = hh(b, c, d, a, k[6], 23, 76029189);\n a = hh(a, b, c, d, k[9], 4, -640364487);\n d = hh(d, a, b, c, k[12], 11, -421815835);\n c = hh(c, d, a, b, k[15], 16, 530742520);\n b = hh(b, c, d, a, k[2], 23, -995338651);\n\n a = ii(a, b, c, d, k[0], 6, -198630844);\n d = ii(d, a, b, c, k[7], 10, 1126891415);\n c = ii(c, d, a, b, k[14], 15, -1416354905);\n b = ii(b, c, d, a, k[5], 21, -57434055);\n a = ii(a, b, c, d, k[12], 6, 1700485571);\n d = ii(d, a, b, c, k[3], 10, -1894986606);\n c = ii(c, d, a, b, k[10], 15, -1051523);\n b = ii(b, c, d, a, k[1], 21, -2054922799);\n a = ii(a, b, c, d, k[8], 6, 1873313359);\n d = ii(d, a, b, c, k[15], 10, -30611744);\n c = ii(c, d, a, b, k[6], 15, -1560198380);\n b = ii(b, c, d, a, k[13], 21, 1309151649);\n a = ii(a, b, c, d, k[4], 6, -145523070);\n d = ii(d, a, b, c, k[11], 10, -1120210379);\n c = ii(c, d, a, b, k[2], 15, 718787259);\n b = ii(b, c, d, a, k[9], 21, -343485551);\n\n x[0] = add32(a, x[0]);\n x[1] = add32(b, x[1]);\n x[2] = add32(c, x[2]);\n x[3] = add32(d, x[3]);\n}\n\nfunction md5blk(s: string): number[] {\n const md5blks: number[] = [];\n for (let i = 0; i < 64; i += 4) {\n md5blks[i >> 2] =\n s.charCodeAt(i) +\n (s.charCodeAt(i + 1) << 8) +\n (s.charCodeAt(i + 2) << 16) +\n (s.charCodeAt(i + 3) << 24);\n }\n return md5blks;\n}\n\nfunction rhex(n: number): string {\n const hexChr = '0123456789abcdef';\n let s = '';\n for (let j = 0; j < 4; j++) {\n s += hexChr.charAt((n >> (j * 8 + 4)) & 0x0f) + hexChr.charAt((n >> (j * 8)) & 0x0f);\n }\n return s;\n}\n\nfunction hex(x: number[]): string {\n return x.map(rhex).join('');\n}\n\nfunction toUTF8(str: string): string {\n return unescape(encodeURIComponent(str));\n}\n\n/**\n * 简化版MD5实现\n * 注意:这是一个轻量级实现,适用于指纹哈希场景\n * 如果项目中已有crypto库,可以直接使用\n */\nexport function md5(input: string): string {\n const s = toUTF8(input);\n const n = s.length;\n const state = [1732584193, -271733879, -1732584194, 271733878];\n let i: number;\n\n for (i = 64; i <= n; i += 64) {\n md5cycle(state, md5blk(s.substring(i - 64, i)));\n }\n\n const tail = s.substring(i - 64);\n const arr = Array(16).fill(0);\n\n for (i = 0; i < tail.length; i++) {\n arr[i >> 2] |= tail.charCodeAt(i) << ((i % 4) << 3);\n }\n arr[i >> 2] |= 0x80 << ((i % 4) << 3);\n\n if (i > 55) {\n md5cycle(state, arr);\n arr.fill(0);\n }\n\n arr[14] = n * 8;\n md5cycle(state, arr);\n\n return hex(state);\n}\n\n/**\n * 生成随机UUID作为兜底方案\n */\nexport function generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID().replace(/-/g, '');\n }\n\n // 兼容性实现\n return 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/x/g, () => {\n return Math.floor(Math.random() * 16).toString(16);\n });\n}\n","/**\n * Canvas 指纹采集器\n * @description 通过Canvas绘制特定图形,利用不同设备的渲染差异生成指纹\n * 参考 FingerprintJS 的噪声检测策略:双重编码检测浏览器是否添加随机噪声\n */\n\nimport { CollectorResult, ICollector, CollectorConfig } from '../types';\nimport { CollectorName } from '../constants';\n\nexport class CanvasCollector implements ICollector {\n readonly name = CollectorName.Canvas;\n\n /**\n * 检测是否为已知会添加 Canvas 噪声的浏览器\n * Safari 17+ 在隐私模式下会添加一致的会话噪声(每次调用相同,但与正常模式不同)\n */\n private isKnownNoisyBrowser(): boolean {\n const ua = navigator.userAgent;\n\n // 检测 Safari 17+\n const safariMatch = ua.match(/Version\\/(\\d+).*Safari/);\n if (safariMatch && parseInt(safariMatch[1], 10) >= 17) {\n return true;\n }\n\n return false;\n }\n\n async collect(_config?: CollectorConfig): Promise<CollectorResult> {\n try {\n // 检测已知会添加噪声的浏览器\n if (this.isKnownNoisyBrowser()) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: 'Browser known for canvas anti-fingerprinting',\n };\n }\n\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: 'Canvas context not available',\n };\n }\n\n canvas.width = 200;\n canvas.height = 50;\n\n // 绘制背景\n ctx.fillStyle = '#f60';\n ctx.fillRect(0, 0, 200, 50);\n\n // 绘制文本(不同设备字体渲染有差异)\n // 使用内置字体避免字体偏好差异\n ctx.fillStyle = '#069';\n ctx.font = '14px Arial';\n ctx.fillText('Device Fingerprint Canvas', 2, 15);\n\n // 绘制更多文本和特殊字符\n ctx.fillStyle = 'rgba(102, 204, 0, 0.7)';\n ctx.font = '18px Times New Roman';\n ctx.fillText('!@#$%^&*()_+-=[]{}|;:', 4, 35);\n\n // 添加圆弧和渐变(增加差异化)\n ctx.beginPath();\n ctx.arc(150, 25, 20, 0, Math.PI * 2, true);\n ctx.closePath();\n ctx.fillStyle = '#ff0';\n ctx.fill();\n\n // 添加阴影效果\n ctx.shadowBlur = 10;\n ctx.shadowColor = 'blue';\n ctx.fillRect(160, 10, 30, 30);\n\n // 噪声检测:双重编码同一画布,比较结果\n // 如果浏览器添加了随机噪声(如无痕模式),两次编码结果会不同\n const dataUrl1 = canvas.toDataURL('image/png');\n const dataUrl2 = canvas.toDataURL('image/png');\n\n if (dataUrl1 !== dataUrl2) {\n // 检测到噪声,标记为不稳定,不参与指纹计算\n return {\n name: this.name,\n value: '',\n success: false,\n error: 'Canvas noise detected (unstable)',\n };\n }\n\n return {\n name: this.name,\n value: dataUrl1,\n success: true,\n };\n } catch (error) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","/**\n * WebGL 指纹采集器\n * @description 通过WebGL获取GPU渲染器信息,不同显卡有不同的标识\n */\n\nimport { CollectorResult, ICollector, CollectorConfig } from '../types';\nimport { CollectorName } from '../constants';\n\nexport class WebGLCollector implements ICollector {\n readonly name = CollectorName.WebGL;\n\n async collect(_config?: CollectorConfig): Promise<CollectorResult> {\n try {\n const canvas = document.createElement('canvas');\n const gl =\n canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n\n if (!gl) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: 'WebGL not available',\n };\n }\n\n const webglContext = gl as WebGLRenderingContext;\n const debugInfo = webglContext.getExtension('WEBGL_debug_renderer_info');\n\n const components: string[] = [];\n\n // 获取GPU渲染器信息\n if (debugInfo) {\n const vendor = webglContext.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);\n const renderer = webglContext.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);\n components.push(`vendor:${vendor}`);\n components.push(`renderer:${renderer}`);\n }\n\n // 获取WebGL基础参数\n components.push(`version:${webglContext.getParameter(webglContext.VERSION)}`);\n components.push(`shadingLanguageVersion:${webglContext.getParameter(webglContext.SHADING_LANGUAGE_VERSION)}`);\n\n // 获取最大纹理尺寸(不同GPU有差异)\n components.push(`maxTextureSize:${webglContext.getParameter(webglContext.MAX_TEXTURE_SIZE)}`);\n components.push(`maxRenderbufferSize:${webglContext.getParameter(webglContext.MAX_RENDERBUFFER_SIZE)}`);\n components.push(`maxViewportDims:${webglContext.getParameter(webglContext.MAX_VIEWPORT_DIMS)}`);\n components.push(`maxVertexAttribs:${webglContext.getParameter(webglContext.MAX_VERTEX_ATTRIBS)}`);\n components.push(`maxVertexUniformVectors:${webglContext.getParameter(webglContext.MAX_VERTEX_UNIFORM_VECTORS)}`);\n components.push(`maxFragmentUniformVectors:${webglContext.getParameter(webglContext.MAX_FRAGMENT_UNIFORM_VECTORS)}`);\n\n // 获取支持的扩展列表\n const extensions = webglContext.getSupportedExtensions() || [];\n components.push(`extensions:${extensions.sort().join(',')}`);\n\n return {\n name: this.name,\n value: components.join('|'),\n success: true,\n };\n } catch (error) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","/**\n * Audio 指纹采集器\n * @description 通过 OfflineAudioContext 生成音频信号,不同设备的音频处理有细微差异\n * @note 使用 OfflineAudioContext 替代已废弃的 ScriptProcessorNode,更加现代化且性能更好\n * 参考 FingerprintJS 的噪声检测策略:检测已知会添加噪声的浏览器\n */\n\nimport { CollectorResult, ICollector, CollectorConfig } from '../types';\nimport { CollectorName } from '../constants';\n\nexport class AudioCollector implements ICollector {\n readonly name = CollectorName.Audio;\n\n /**\n * 检测是否为已知会添加音频噪声的浏览器\n * Safari 17+ 和 Samsung Internet 26+ 在隐私模式下会添加噪声\n */\n private isKnownNoisyBrowser(): boolean {\n const ua = navigator.userAgent;\n\n // 检测 Safari 17+\n const safariMatch = ua.match(/Version\\/(\\d+).*Safari/);\n if (safariMatch && parseInt(safariMatch[1], 10) >= 17) {\n return true;\n }\n\n // 检测 Samsung Internet 26+\n const samsungMatch = ua.match(/SamsungBrowser\\/(\\d+)/);\n if (samsungMatch && parseInt(samsungMatch[1], 10) >= 26) {\n return true;\n }\n\n return false;\n }\n\n async collect(_config?: CollectorConfig): Promise<CollectorResult> {\n try {\n // 检测已知会添加噪声的浏览器\n if (this.isKnownNoisyBrowser()) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: 'Browser known for audio anti-fingerprinting',\n };\n }\n\n // 检查 OfflineAudioContext 支持\n const OfflineAudioContextClass =\n window.OfflineAudioContext || (window as any).webkitOfflineAudioContext;\n\n if (!OfflineAudioContextClass) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: 'OfflineAudioContext not available',\n };\n }\n\n // 创建离线音频上下文\n // 参数: 声道数, 采样帧数, 采样率\n const sampleRate = 44100;\n const duration = 0.5; // 500ms\n const length = sampleRate * duration;\n const context = new OfflineAudioContextClass(1, length, sampleRate);\n\n // 创建振荡器\n const oscillator = context.createOscillator();\n oscillator.type = 'triangle';\n oscillator.frequency.setValueAtTime(10000, context.currentTime);\n\n // 创建压缩器(增加设备差异性)\n const compressor = context.createDynamicsCompressor();\n compressor.threshold.setValueAtTime(-50, context.currentTime);\n compressor.knee.setValueAtTime(40, context.currentTime);\n compressor.ratio.setValueAtTime(12, context.currentTime);\n compressor.attack.setValueAtTime(0, context.currentTime);\n compressor.release.setValueAtTime(0.25, context.currentTime);\n\n // 连接节点: 振荡器 -> 压缩器 -> 目标\n oscillator.connect(compressor);\n compressor.connect(context.destination);\n\n // 启动振荡器\n oscillator.start(0);\n\n // 渲染音频并获取结果\n const renderedBuffer = await context.startRendering();\n const channelData = renderedBuffer.getChannelData(0);\n\n // 从音频数据中提取指纹特征\n // 采样策略:从多个位置采样以增加稳定性\n const fingerprints: number[] = [];\n const samplePoints = [\n 4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000, 8500, 9000,\n 9500, 10000, 10500, 11000, 11500, 12000, 12500, 13000, 13500, 14000,\n ];\n\n for (const point of samplePoints) {\n if (point < channelData.length) {\n fingerprints.push(channelData[point]);\n }\n }\n\n // 计算音频特征的统计值(增加稳定性)\n const sum = fingerprints.reduce((a, b) => a + b, 0);\n const avg = sum / fingerprints.length;\n const variance = fingerprints.reduce((acc, val) => acc + Math.pow(val - avg, 2), 0) / fingerprints.length;\n\n // 组合指纹值:采样点 + 统计特征\n const value = [\n ...fingerprints.map((v) => v.toFixed(8)),\n `avg:${avg.toFixed(8)}`,\n `var:${variance.toFixed(8)}`,\n ].join(',');\n\n return {\n name: this.name,\n value,\n success: true,\n };\n } catch (error) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","/**\n * 屏幕信息采集器\n * @description 采集屏幕分辨率、色深、像素比等信息\n */\n\nimport { CollectorResult, ICollector, CollectorConfig } from '../types';\nimport { CollectorName } from '../constants';\n\nexport class ScreenCollector implements ICollector {\n readonly name = CollectorName.Screen;\n\n /**\n * 检测是否为 Safari 17+\n * Safari 17+ 在无痕模式下会返回窗口尺寸而非屏幕分辨率\n */\n private isSafari17Plus(): boolean {\n const ua = navigator.userAgent;\n const safariMatch = ua.match(/Version\\/(\\d+).*Safari/);\n return !!(safariMatch && parseInt(safariMatch[1], 10) >= 17);\n }\n\n async collect(_config?: CollectorConfig): Promise<CollectorResult> {\n try {\n const components: string[] = [];\n const isSafari17Plus = this.isSafari17Plus();\n\n // Safari 17+ 无痕模式会返回窗口尺寸,跳过这些不稳定的属性\n if (!isSafari17Plus) {\n // 屏幕分辨率\n components.push(`width:${screen.width}`);\n components.push(`height:${screen.height}`);\n\n // 可用区域\n components.push(`availWidth:${screen.availWidth}`);\n components.push(`availHeight:${screen.availHeight}`);\n }\n\n // 色深\n components.push(`colorDepth:${screen.colorDepth}`);\n components.push(`pixelDepth:${screen.pixelDepth}`);\n\n // 设备像素比\n components.push(`devicePixelRatio:${window.devicePixelRatio || 1}`);\n\n // 屏幕方向\n if (screen.orientation) {\n components.push(`orientation:${screen.orientation.type}`);\n }\n\n // 触摸支持\n const maxTouchPoints = navigator.maxTouchPoints || 0;\n components.push(`maxTouchPoints:${maxTouchPoints}`);\n components.push(`touchSupport:${maxTouchPoints > 0}`);\n\n return {\n name: this.name,\n value: components.join('|'),\n success: true,\n };\n } catch (error) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","/**\n * 系统信息采集器\n * @description 采集时区、语言、硬件并发数、内存等系统级信息\n */\n\nimport { CollectorResult, ICollector, CollectorConfig } from '../types';\nimport { CollectorName } from '../constants';\n\nexport class SystemCollector implements ICollector {\n readonly name = CollectorName.System;\n\n async collect(config?: CollectorConfig): Promise<CollectorResult> {\n try {\n const components: string[] = [];\n\n // 严格浏览器模式:加入 User-Agent 以区分不同浏览器\n if (config?.strictBrowserMode) {\n components.push(`userAgent:${navigator.userAgent}`);\n }\n\n // 时区\n components.push(`timezone:${Intl.DateTimeFormat().resolvedOptions().timeZone}`);\n components.push(`timezoneOffset:${new Date().getTimezoneOffset()}`);\n\n // 语言设置(只使用主语言,navigator.languages 在无痕模式下会被截断)\n components.push(`language:${navigator.language}`);\n\n // 硬件并发数(CPU核心数)\n components.push(`hardwareConcurrency:${navigator.hardwareConcurrency || 'unknown'}`);\n\n // 设备内存(仅Chrome支持)\n const deviceMemory = (navigator as any).deviceMemory;\n if (deviceMemory) {\n components.push(`deviceMemory:${deviceMemory}`);\n }\n\n // 平台信息\n components.push(`platform:${navigator.platform}`);\n\n // 是否启用Cookie\n components.push(`cookieEnabled:${navigator.cookieEnabled}`);\n\n // 是否启用Java\n components.push(`javaEnabled:${typeof navigator.javaEnabled === 'function' ? navigator.javaEnabled() : false}`);\n\n // Do Not Track 设置\n const doNotTrack = navigator.doNotTrack || (window as any).doNotTrack;\n components.push(`doNotTrack:${doNotTrack || 'unknown'}`);\n\n // PDF查看器支持\n components.push(`pdfViewerEnabled:${(navigator as any).pdfViewerEnabled ?? 'unknown'}`);\n\n // WebDriver检测(防止自动化工具)\n components.push(`webdriver:${navigator.webdriver || false}`);\n\n return {\n name: this.name,\n value: components.join('|'),\n success: true,\n };\n } catch (error) {\n return {\n name: this.name,\n value: '',\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n };\n }\n }\n}\n","/**\n * 采集器统一导出\n */\n\nexport { CanvasCollector } from './canvas';\nexport { WebGLCollector } from './webgl';\nexport { AudioCollector } from './audio';\nexport { ScreenCollector } from './screen';\nexport { SystemCollector } from './system';\n\nimport { ICollector } from '../types';\nimport { CanvasCollector } from './canvas';\nimport { WebGLCollector } from './webgl';\nimport { AudioCollector } from './audio';\nimport { ScreenCollector } from './screen';\nimport { SystemCollector } from './system';\n\n/**\n * 创建所有采集器实例\n */\nexport function createCollectors(): ICollector[] {\n return [\n new CanvasCollector(),\n new WebGLCollector(),\n new AudioCollector(),\n new ScreenCollector(),\n new SystemCollector(),\n ];\n}\n","/**\n * localStorage 存储实现\n */\n\nimport { CachedFingerprint, IStorage } from '../types';\nimport { STORAGE_KEY } from '../constants';\n\nexport class LocalStorageAdapter implements IStorage {\n private readonly key: string;\n\n constructor(prefix?: string) {\n this.key = prefix ? `${prefix}_${STORAGE_KEY}` : STORAGE_KEY;\n }\n\n async get(): Promise<CachedFingerprint | null> {\n try {\n const data = localStorage.getItem(this.key);\n if (!data) {\n return null;\n }\n return JSON.parse(data) as CachedFingerprint;\n } catch {\n return null;\n }\n }\n\n async set(data: CachedFingerprint): Promise<void> {\n try {\n localStorage.setItem(this.key, JSON.stringify(data));\n } catch (error) {\n console.warn('[Fingerprint] Failed to save to localStorage:', error);\n }\n }\n\n async clear(): Promise<void> {\n try {\n localStorage.removeItem(this.key);\n } catch {\n // 忽略清除错误\n }\n }\n}\n","/**\n * IndexedDB 存储实现\n * @description 相比localStorage更难被用户清除,提供更好的持久性\n */\n\nimport { CachedFingerprint, IStorage } from '../types';\nimport { IDB_DATABASE_NAME, IDB_STORE_NAME, STORAGE_KEY } from '../constants';\n\nexport class IndexedDBAdapter implements IStorage {\n private readonly dbName: string;\n private readonly storeName: string;\n private readonly key: string;\n private db: IDBDatabase | null = null;\n\n constructor(prefix?: string) {\n this.dbName = prefix ? `${prefix}_${IDB_DATABASE_NAME}` : IDB_DATABASE_NAME;\n this.storeName = IDB_STORE_NAME;\n this.key = STORAGE_KEY;\n }\n\n private async openDB(): Promise<IDBDatabase> {\n if (this.db) {\n return this.db;\n }\n\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1);\n\n request.onerror = () => {\n reject(new Error('Failed to open IndexedDB'));\n };\n\n request.onsuccess = () => {\n this.db = request.result;\n resolve(request.result);\n };\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName, { keyPath: 'id' });\n }\n };\n });\n }\n\n async get(): Promise<CachedFingerprint | null> {\n try {\n const db = await this.openDB();\n return new Promise((resolve) => {\n const transaction = db.transaction(this.storeName, 'readonly');\n const store = transaction.objectStore(this.storeName);\n const request = store.get(this.key);\n\n request.onerror = () => {\n resolve(null);\n };\n\n request.onsuccess = () => {\n const result = request.result;\n if (result && result.data) {\n resolve(result.data as CachedFingerprint);\n } else {\n resolve(null);\n }\n };\n });\n } catch {\n return null;\n }\n }\n\n async set(data: CachedFingerprint): Promise<void> {\n try {\n const db = await this.openDB();\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n const request = store.put({ id: this.key, data });\n\n request.onerror = () => {\n reject(new Error('Failed to save to IndexedDB'));\n };\n\n request.onsuccess = () => {\n resolve();\n };\n });\n } catch (error) {\n console.warn('[Fingerprint] Failed to save to IndexedDB:', error);\n }\n }\n\n async clear(): Promise<void> {\n try {\n const db = await this.openDB();\n return new Promise((resolve) => {\n const transaction = db.transaction(this.storeName, 'readwrite');\n const store = transaction.objectStore(this.storeName);\n store.delete(this.key);\n resolve();\n });\n } catch {\n // 忽略清除错误\n }\n }\n}\n","/**\n * 指纹管理器 - 核心调度\n * @description 协调采集器、存储、缓存的核心类\n */\n\nimport {\n FingerprintResult,\n CachedFingerprint,\n FingerprintConfig,\n ICollector,\n IStorage,\n CollectorConfig,\n DebugInfo,\n CollectorDebugInfo\n} from '../types';\nimport { DEFAULT_CACHE_EXPIRY, CURRENT_VERSION } from '../constants';\nimport { md5, generateUUID } from './hash';\nimport { createCollectors } from '../collectors';\nimport { LocalStorageAdapter } from '../storage/local-storage';\nimport { IndexedDBAdapter } from '../storage/indexed-db';\n\nexport class FingerprintManager {\n private config: Required<FingerprintConfig>;\n private collectors: ICollector[];\n private localStorage: IStorage;\n private indexedDB: IStorage | null;\n private cachedResult: FingerprintResult | null = null;\n\n constructor(config: FingerprintConfig = {}) {\n this.config = {\n cacheExpiry: config.cacheExpiry ?? DEFAULT_CACHE_EXPIRY,\n enableIndexedDB: config.enableIndexedDB ?? true,\n storageKeyPrefix: config.storageKeyPrefix ?? 'df',\n version: config.version ?? CURRENT_VERSION,\n strictBrowserMode: config.strictBrowserMode ?? false,\n debug: config.debug ?? false,\n };\n\n this.collectors = createCollectors();\n this.localStorage = new LocalStorageAdapter(this.config.storageKeyPrefix);\n this.indexedDB = this.config.enableIndexedDB\n ? new IndexedDBAdapter(this.config.storageKeyPrefix)\n : null;\n }\n\n /**\n * 获取设备指纹\n * @returns 指纹结果\n */\n async getFingerprint(): Promise<FingerprintResult> {\n // 1. 检查内存缓存\n if (this.cachedResult && !this.isExpired(this.cachedResult.expiresAt)) {\n return this.cachedResult;\n }\n\n // 2. 检查localStorage缓存\n const localCache = await this.localStorage.get();\n if (localCache && !this.isExpired(localCache.expiresAt)) {\n this.cachedResult = this.toResult(localCache);\n return this.cachedResult;\n }\n\n // 3. 检查IndexedDB缓存\n if (this.indexedDB) {\n const idbCache = await this.indexedDB.get();\n if (idbCache && !this.isExpired(idbCache.expiresAt)) {\n // 同步到localStorage\n await this.localStorage.set(idbCache);\n this.cachedResult = this.toResult(idbCache);\n return this.cachedResult;\n }\n }\n\n // 4. 重新采集指纹\n return this.collectAndCache();\n }\n\n /**\n * 强制重新采集指纹\n */\n async refresh(): Promise<FingerprintResult> {\n return this.collectAndCache();\n }\n\n /**\n * 清除缓存\n */\n async clear(): Promise<void> {\n this.cachedResult = null;\n await this.localStorage.clear();\n if (this.indexedDB) {\n await this.indexedDB.clear();\n }\n }\n\n /**\n * 采集并缓存指纹\n */\n private async collectAndCache(): Promise<FingerprintResult> {\n const { fingerprint, isFallback, debugInfo } = await this.collect();\n const now = Date.now();\n const cached: CachedFingerprint = {\n fingerprint,\n isFallback,\n createdAt: now,\n expiresAt: now + this.config.cacheExpiry,\n version: this.config.version,\n };\n\n // 双重存储\n await this.localStorage.set(cached);\n if (this.indexedDB) {\n await this.indexedDB.set(cached);\n }\n\n this.cachedResult = this.toResult(cached, debugInfo);\n return this.cachedResult;\n }\n\n /**\n * 执行采集\n */\n private async collect(): Promise<{ fingerprint: string; isFallback: boolean; debugInfo?: DebugInfo }> {\n const startTime = performance.now();\n const collectorDebugInfos: CollectorDebugInfo[] = [];\n\n // 调试模式:输出开始采集日志\n if (this.config.debug) {\n console.group('[Fingerprint] 开始采集指纹');\n console.log('配置:', this.config);\n console.log('User-Agent:', navigator.userAgent);\n }\n\n try {\n // 采集器配置\n const collectorConfig: CollectorConfig = {\n strictBrowserMode: this.config.strictBrowserMode,\n };\n\n // 并行执行所有采集器,同时记录每个采集器的耗时\n const results = await Promise.all(\n this.collectors.map(async (collector) => {\n const collectorStart = performance.now();\n const result = await collector.collect(collectorConfig);\n const collectorDuration = performance.now() - collectorStart;\n\n // 收集调试信息\n const debugItem: CollectorDebugInfo = {\n name: result.name,\n success: result.success,\n duration: Math.round(collectorDuration * 100) / 100,\n value: result.value ? result.value.substring(0, 200) : '',\n valueLength: result.value?.length || 0,\n valueHash: result.value ? md5(result.value) : '',\n error: result.error,\n };\n collectorDebugInfos.push(debugItem);\n\n // 调试模式:输出每个采集器的结果\n if (this.config.debug) {\n const status = result.success ? '✓' : '✗';\n const color = result.success ? 'color: #10b981' : 'color: #ef4444';\n console.log(\n `%c${status} ${result.name}`,\n color,\n `| 耗时: ${debugItem.duration}ms`,\n `| 长度: ${debugItem.valueLength}`,\n `| 哈希: ${debugItem.valueHash.substring(0, 8)}...`,\n result.error ? `| 错误: ${result.error}` : ''\n );\n // 输出完整原始值(用于对比分析)\n console.log(` └─ 原始值:`, result.value || '(空)');\n }\n\n return result;\n })\n );\n\n // 过滤成功的结果\n const successResults = results.filter((r) => r.success && r.value);\n\n if (successResults.length === 0) {\n // 全部失败,使用兜底UUID\n const fallbackFingerprint = generateUUID();\n const totalDuration = Math.round((performance.now() - startTime) * 100) / 100;\n\n if (this.config.debug) {\n console.warn('[Fingerprint] 所有采集器失败,使用兜底 UUID:', fallbackFingerprint);\n console.log(`[Fingerprint] 总耗时: ${totalDuration}ms`);\n console.groupEnd();\n }\n\n return {\n fingerprint: fallbackFingerprint,\n isFallback: true,\n debugInfo: this.config.debug ? {\n duration: totalDuration,\n collectors: collectorDebugInfos,\n rawData: '',\n userAgent: navigator.userAgent,\n } : undefined,\n };\n }\n\n // 拼接所有采集值并计算哈希\n const rawData = successResults\n .map((r) => `${r.name}:${r.value}`)\n .sort()\n .join('|');\n\n const fingerprint = md5(rawData);\n const totalDuration = Math.round((performance.now() - startTime) * 100) / 100;\n\n // 调试模式:输出最终结果\n if (this.config.debug) {\n console.log('[Fingerprint] 成功采集器:', successResults.map(r => r.name).join(', '));\n console.log('[Fingerprint] 原始数据长度:', rawData.length);\n console.log('[Fingerprint] 最终指纹:', fingerprint);\n console.log(`[Fingerprint] 总耗时: ${totalDuration}ms`);\n console.groupEnd();\n }\n\n return {\n fingerprint,\n isFallback: false,\n debugInfo: this.config.debug ? {\n duration: totalDuration,\n collectors: collectorDebugInfos,\n rawData,\n userAgent: navigator.userAgent,\n } : undefined,\n };\n } catch (error) {\n const totalDuration = Math.round((performance.now() - startTime) * 100) / 100;\n const fallbackFingerprint = generateUUID();\n\n if (this.config.debug) {\n console.error('[Fingerprint] 采集异常:', error);\n console.warn('[Fingerprint] 使用兜底 UUID:', fallbackFingerprint);\n console.log(`[Fingerprint] 总耗时: ${totalDuration}ms`);\n console.groupEnd();\n } else {\n console.warn('[Fingerprint] Collection failed, using fallback UUID:', error);\n }\n\n return {\n fingerprint: fallbackFingerprint,\n isFallback: true,\n debugInfo: this.config.debug ? {\n duration: totalDuration,\n collectors: collectorDebugInfos,\n rawData: '',\n userAgent: navigator.userAgent,\n } : undefined,\n };\n }\n }\n\n /**\n * 检查是否过期\n */\n private isExpired(expiresAt: number): boolean {\n return Date.now() > expiresAt;\n }\n\n /**\n * 转换为结果对象\n */\n private toResult(cached: CachedFingerprint, debugInfo?: DebugInfo): FingerprintResult {\n const result: FingerprintResult = {\n fingerprint: cached.fingerprint,\n isFallback: cached.isFallback,\n timestamp: cached.createdAt,\n expiresAt: cached.expiresAt,\n };\n\n if (debugInfo) {\n result.debug = debugInfo;\n }\n\n return result;\n }\n}\n","/**\n * 设备指纹模块 - 主入口\n *\n * @description\n * 独立、高内聚的设备指纹模块,便于复用到其他系统。\n *\n * @example\n * ```typescript\n * import { getDeviceFingerprint, initFingerprint } from 'src/utils/fingerprint';\n *\n * // 方式1: 使用默认配置\n * const fp = await getDeviceFingerprint();\n * console.log(fp.fingerprint); // 32位MD5哈希\n *\n * // 方式2: 自定义配置\n * initFingerprint({\n * cacheExpiry: 7 * 24 * 60 * 60 * 1000, // 7天\n * storageKeyPrefix: 'myapp',\n * });\n * const fp2 = await getDeviceFingerprint();\n * ```\n *\n * @author IDaaS Team\n * @version 1.0.0\n */\n\nimport { FingerprintManager } from './core/fingerprint-manager';\nimport { FingerprintResult, FingerprintConfig } from './types';\nimport { HTTP_HEADER_NAME } from './constants';\n\n// 单例实例\nlet manager: FingerprintManager | null = null;\n\n/**\n * 初始化指纹模块(可选)\n * @param config 配置选项\n */\nexport function initFingerprint(config?: FingerprintConfig): void {\n manager = new FingerprintManager(config);\n}\n\n/**\n * 获取指纹管理器实例\n */\nfunction getManager(): FingerprintManager {\n if (!manager) {\n manager = new FingerprintManager();\n }\n return manager;\n}\n\n/**\n * 获取设备指纹\n * @returns 指纹结果\n */\nexport async function getDeviceFingerprint(): Promise<FingerprintResult> {\n return getManager().getFingerprint();\n}\n\n/**\n * 获取指纹值(简化版,仅返回哈希字符串)\n * @returns 32位MD5哈希字符串\n */\nexport async function getFingerprint(): Promise<string> {\n const result = await getManager().getFingerprint();\n return result.fingerprint;\n}\n\n/**\n * 强制刷新指纹\n * @returns 新的指纹结果\n */\nexport async function refreshFingerprint(): Promise<FingerprintResult> {\n return getManager().refresh();\n}\n\n/**\n * 清除指纹缓存\n */\nexport async function clearFingerprint(): Promise<void> {\n return getManager().clear();\n}\n\n/**\n * 获取HTTP Header名称\n */\nexport function getHeaderName(): string {\n return HTTP_HEADER_NAME;\n}\n\n// 导出类型和常量(便于外部使用)\nexport type { FingerprintResult, FingerprintConfig } from './types';\nexport { HTTP_HEADER_NAME } from './constants';\n"]}
package/dist/index.d.mts CHANGED
@@ -12,6 +12,36 @@ interface FingerprintResult {
12
12
  timestamp: number;
13
13
  /** 过期时间戳 */
14
14
  expiresAt: number;
15
+ /** 调试信息(仅在 debug 模式下返回) */
16
+ debug?: DebugInfo;
17
+ }
18
+ /** 调试信息 */
19
+ interface DebugInfo {
20
+ /** 采集耗时(毫秒) */
21
+ duration: number;
22
+ /** 各采集器的详细结果 */
23
+ collectors: CollectorDebugInfo[];
24
+ /** 原始数据(用于哈希的拼接字符串) */
25
+ rawData: string;
26
+ /** 浏览器 User-Agent */
27
+ userAgent: string;
28
+ }
29
+ /** 采集器调试信息 */
30
+ interface CollectorDebugInfo {
31
+ /** 采集器名称 */
32
+ name: string;
33
+ /** 是否成功 */
34
+ success: boolean;
35
+ /** 采集耗时(毫秒) */
36
+ duration: number;
37
+ /** 原始值(截断显示) */
38
+ value: string;
39
+ /** 原始值长度 */
40
+ valueLength: number;
41
+ /** 原始值的哈希(用于对比) */
42
+ valueHash: string;
43
+ /** 错误信息 */
44
+ error?: string;
15
45
  }
16
46
  /** 指纹管理器配置 */
17
47
  interface FingerprintConfig {
@@ -23,6 +53,19 @@ interface FingerprintConfig {
23
53
  storageKeyPrefix?: string;
24
54
  /** 当前版本号 */
25
55
  version?: number;
56
+ /**
57
+ * 严格浏览器模式,默认false
58
+ * 启用后会在指纹计算中加入浏览器特征(User-Agent),
59
+ * 使得同一设备上不同浏览器产生不同指纹。
60
+ * 注意:这不符合设备指纹的标准定义,仅用于特殊业务场景。
61
+ */
62
+ strictBrowserMode?: boolean;
63
+ /**
64
+ * 调试模式,默认false
65
+ * 启用后会在返回结果中包含详细的调试信息,
66
+ * 包括各采集器的耗时、原始值、哈希值等。
67
+ */
68
+ debug?: boolean;
26
69
  }
27
70
 
28
71
  /** HTTP Header 名称 */
package/dist/index.d.ts CHANGED
@@ -12,6 +12,36 @@ interface FingerprintResult {
12
12
  timestamp: number;
13
13
  /** 过期时间戳 */
14
14
  expiresAt: number;
15
+ /** 调试信息(仅在 debug 模式下返回) */
16
+ debug?: DebugInfo;
17
+ }
18
+ /** 调试信息 */
19
+ interface DebugInfo {
20
+ /** 采集耗时(毫秒) */
21
+ duration: number;
22
+ /** 各采集器的详细结果 */
23
+ collectors: CollectorDebugInfo[];
24
+ /** 原始数据(用于哈希的拼接字符串) */
25
+ rawData: string;
26
+ /** 浏览器 User-Agent */
27
+ userAgent: string;
28
+ }
29
+ /** 采集器调试信息 */
30
+ interface CollectorDebugInfo {
31
+ /** 采集器名称 */
32
+ name: string;
33
+ /** 是否成功 */
34
+ success: boolean;
35
+ /** 采集耗时(毫秒) */
36
+ duration: number;
37
+ /** 原始值(截断显示) */
38
+ value: string;
39
+ /** 原始值长度 */
40
+ valueLength: number;
41
+ /** 原始值的哈希(用于对比) */
42
+ valueHash: string;
43
+ /** 错误信息 */
44
+ error?: string;
15
45
  }
16
46
  /** 指纹管理器配置 */
17
47
  interface FingerprintConfig {
@@ -23,6 +53,19 @@ interface FingerprintConfig {
23
53
  storageKeyPrefix?: string;
24
54
  /** 当前版本号 */
25
55
  version?: number;
56
+ /**
57
+ * 严格浏览器模式,默认false
58
+ * 启用后会在指纹计算中加入浏览器特征(User-Agent),
59
+ * 使得同一设备上不同浏览器产生不同指纹。
60
+ * 注意:这不符合设备指纹的标准定义,仅用于特殊业务场景。
61
+ */
62
+ strictBrowserMode?: boolean;
63
+ /**
64
+ * 调试模式,默认false
65
+ * 启用后会在返回结果中包含详细的调试信息,
66
+ * 包括各采集器的耗时、原始值、哈希值等。
67
+ */
68
+ debug?: boolean;
26
69
  }
27
70
 
28
71
  /** HTTP Header 名称 */