0

我想覆蓋內置方法CanvasRenderingContext2D.getImageData()。我想覆蓋實現,以便修改後的函數使用canvas上下文來修改畫布,然後調用原始函數,該函數應該返回不同的數據,如果該函數未被覆蓋。我這樣做的原因是爲了防止瀏覽器指紋。覆蓋CanvasRenderingContext2D.getImageData()

canvas.js

(function(){ 
    'use strict'; 

    var originalGetImageData = CanvasRenderingContext2D.prototype.getImageData; 

    // This function just adds 1 to each RGBA component in the array for testing. 
    // Will add random values for the real thing. 
    function randomiseImageData(image) {   
     var imageData = image.data; 

     var imageLength = imageData.length; 

     for (var i = 0; i < imageLength; i++) { 
      imageData[i] += 1; 
     } 

     var modifiedImage = new ImageData(image.width, image.height); 

     return modifiedImage; 
    } 

    CanvasRenderingContext2D.prototype.getImageData = function(sx, sy, sw, sh) { 
     console.log("[ALERT] " + window.location.hostname + " called CanvasRenderingContext2D.getImageData()"); 

     const origin = window.location.hostname; 

     Math.seedrandom(origin); 

     var image = originalGetImageData.call(this, sx, sy, sw, sh); 

     return randomiseImageData(image); 
    }; 
})(); 
+0

向畫布內容引入額外的熵級別將使瀏覽器更加獨特,從而更容易識別和跟蹤。 – Blindman67

回答

2

你是返回一個新的ImageData對象。

我想你想要的是返回填充的。
由於您已經修改了data數組,您可以簡單地返回原始的ImageData,您的修改已經完成。

// shortened version 
 
(function(){ 
 
const ori = CanvasRenderingContext2D.prototype.getImageData; 
 
CanvasRenderingContext2D.prototype.getImageData = function(){ 
 
    let imageData = ori.apply(this, arguments); 
 
    // modify the Uint8Array 
 
    imageData.data.forEach((v, i, a) => a[i]+=1); 
 
    // return the now modified ImageData 
 
    return imageData; 
 
    }; 
 
})() 
 
    
 
var ctx = document.createElement('canvas').getContext('2d'); 
 
console.log(ctx.getImageData(0,0,1,1));

如果你真的想創建一個新的ImageData,那麼它的

new ImageData(imageData, image.width, image.height); 
//    ^^ 
//   pass the data to fill the new ImageData object 

但是請注意,瀏覽器的支持不是很大,而且你不會贏得任何東西這樣做。

+0

感謝您的幫助。問題出在我用來測試指紋的代碼中,而不是我用來僞造指紋的代碼。現在它全部修好了。 – Snapper26

0

您不能刪除指紋。

更多The Web never forgets

你不能規避指紋。你可以做的最好的是返回最常見的指紋(這是不容易確定的),增加你可能屬於的設備。

返回一組隨機的像素(或每個像素通道增加一個像素)是最差的,如果你是唯一一個這樣做的話。它絕對會將您的瀏覽器標記爲獨一無二的,並讓traking軟件知道返回更改數據的瀏覽器只是一個,或者是一個非常小的瀏覽器。

停止指紋的最好方法是通過一個通用的廣泛採用的數據返回策略。如果每個瀏覽器都返回全零(透明黑色),那麼就沒有唯一性,因此無法根據畫布跟蹤設備。

畫布指紋只是指紋的一部分,還有更多的數據來源幫助識別設備。瀏覽器,瀏覽器版本,操作系統,操作系統版本,屏幕分辨率以及其他一系列清單。即使您將畫布消除爲唯一的來源,除非您對其餘的信息進行相同處理,否則它是毫無意義的。

緩解

所以說這樣的代碼來返回歸零數據如下。

(function() { 
    if (window.CanvasRenderingContext2D) { 
     const gid = CanvasRenderingContext2D.prototype.getImageData; 
     CanvasRenderingContext2D.prototype.getImageData = function (x, y, w, h) { 
      var data = gid.bind(this)(x, y, w, h); 
      data.data.fill(0); // fill with zero 
      return data; 
     } 
     // Token way to avoid JS from finding out that you have overwritten the prototype overwrite 
     // the toString method as well (note ctx.getImageData.toString.toString() will 
     // still show you have changed the prototype but over writing Object.toSting is not worth the problems) 
     CanvasRenderingContext2D.prototype.getImageData.toString = function() { 
      return "function getImageData() { [native code] }"; 
     } 
    } 
}()); 
+0

我同意將每個像素加1的部分都是壞的。也許我應該更清楚地表明這只是爲了測試,我會在稍後提出更好的東西。我也同意你不能阻止指紋,但是我打算做的是在每個站點和會話的基礎上改變我的指紋。在這種情況下,我的指紋的獨特性或共同性如何並不重要。如果您不同意,請告訴我。 – Snapper26

+0

畫布指紋使用每種瀏覽器(和瀏覽器版本)呈現文本的獨特方式。要模擬其他瀏覽器,您需要知道每個瀏覽器的字體,字體大小,字體對齊方式,文本使用方式,文本樣式,背景像素等,所有這些對每個指紋識別服務都是唯一的。您可以捕獲每個瀏覽器的指紋,並將所渲染的指紋替換爲副本,但更智能的指紋會使這種情況變得不切實際(如果他們檢測到計數器打印的話)。除非您在每次瀏覽時使用不同的代理,否則您將被跟蹤。 – Blindman67

+0

同意所有這一切。那麼如何將密碼隨機噪聲引入每個站點和會話的圖像中?由於渲染文本只是最後的像素數據。 – Snapper26