【问题标题】:Getting unique ClientID from chrome extension?从 chrome 扩展中获取唯一的 ClientID?
【发布时间】:2014-07-12 09:31:15
【问题描述】:

我正在开发 chrome 扩展程序。我需要能够将每个客户识别为唯一客户。

我无法将 guid 存储在 cookie 中,因为 cookie 可以删除。我需要从系统本身读取一些独特的东西。

现在 - 我知道 JS 无法访问客户端资源(本地资源)但是 - 这是我的问题:

问题

chrome 扩展 Js 是否提供 API 来获取唯一的客户端信息(我不在乎什么数据 - 只要它是唯一的)。

编辑:

澄清一下:

将向用户显示一个唯一的密钥(这是他计算机的哈希数据)。此代码将发送给我,我将提供匹配结果,用户将被发送(通过电子邮件),然后 - 他将能够使用扩展。

(不,并非所有国家/地区都支持通过钱包支付延期付款,我在其中一个国家/地区)

【问题讨论】:

  • 我认为无法通过 javascript 读取任何硬件 ID 或其他内容,您可以使用此脚本,但我认为它使用 cookie dannytalk.com/read-google-analytics-cookie-script。我通过这篇文章stackoverflow.com/a/12162449/3403216 找到了它。 lg
  • @linluk 这将提供有关安装它的用户数量的信息。我需要唯一 IDentifier 来提供特定的 LicenseeKey
  • 我可能在这里遗漏了一些东西,但你为什么不能使用客户端的 IP 地址(通过 Ajax 调用 php 脚本并返回到你的 javascript)?
  • @myfunkyside ip 在路由器后面不是唯一的

标签: javascript google-chrome google-chrome-extension


【解决方案1】:

为了唯一标识用户,我建议生成一个随机令牌并将其存储在您的扩展程序的存储中 (chrome.storage)。当令牌在存储中不存在时,用户 ID 只需生成一次。

例如:

function getRandomToken() {
    // E.g. 8 * 32 = 256 bits token
    var randomPool = new Uint8Array(32);
    crypto.getRandomValues(randomPool);
    var hex = '';
    for (var i = 0; i < randomPool.length; ++i) {
        hex += randomPool[i].toString(16);
    }
    // E.g. db18458e2782b2b77e36769c569e263a53885a9944dd0a861e5064eac16f1a
    return hex;
}

chrome.storage.sync.get('userid', function(items) {
    var userid = items.userid;
    if (userid) {
        useToken(userid);
    } else {
        userid = getRandomToken();
        chrome.storage.sync.set({userid: userid}, function() {
            useToken(userid);
        });
    }
    function useToken(userid) {
        // TODO: Use user id for authentication or whatever you want.
    }
});

这个机制依赖chrome.storage.sync,相当可靠。此存储的 ID 只会在以下情况下丢失:

  • 用户重新安装扩展程序。卸载扩展程序时,本地存储将被清除。
  • 已超出其中一个存储配额(阅读documentation)。
    这不会发生,因为唯一的写入操作发生在您的扩展程序的第一次运行时。
  • Chrome 的存储已损坏,无法保存数据。
    即使用户没有启用 Chrome 同步,数据仍然会保存在本地。 Chrome 内部存在导致数据丢失的错误,但这些都是偶发事件。
  • 用户打开了您的扩展页面的开发者工具并运行了chrome.storage.sync.clear() 或类似的东西。
    您无法防范那些知道弄乱 Chrome 扩展程序内部结构的用户。

如果你想唯一标识一个用户,前面的方法就足够了。如果您真的想要获得基于硬件的 ID,请同时使用 chrome.storage.cpuchrome.storage.memory。不过,我看不出使用这些额外资源有什么好处,因为如果用户更换硬件,它们可能会发生变化,而且它们也不是唯一的(例如,两台相同的笔记本电脑会报告相同的值)。

【讨论】:

  • 如果生成了 UID,然后用户更改了登录的 Google 帐户,而无需重新启动浏览器,这种方法会发生什么情况?通常同步是事实的来源,但假设在另一个帐户上此扩展尚未初始化。本地状态设置了 UID,云没有记录,我希望它可以愉快地同步到第二个帐户。
  • @Xan 数据确实会同步到两个 Google 帐户。这就是同步在同一配置文件中的工作原理。如果用户想使用其他帐户登录,则他们必须在“设置”页面创建新配置文件并登录以同步该新配置文件。同步的工作原理如下:数据存储在本地,但如果您使用 Google 帐户登录另一台设备,则数据也会与另一台设备同步。如果您只想在同一台计算机上允许一个帐户,请使用 chrome.storage.local 而不是 .sync。不过,这可能会让一些用户生气。
  • OP 要求识别“客户端”,这本身就是模棱两可的,但随后他谈到了基本上是硬件指纹。所以他可能想要local。此外,虽然用户可以擦除存储,但他也可以非常轻松地克隆它。
  • @FlashThunder 我的回答中明确提到了这句话。这是您在获取唯一标识符方面可以获得的最接近的方法。它甚至比 cookie(通常在网站上使用)更可靠。
  • “此存储的 ID 只会在以下罕见情况下丢失”您忘记了一种情况:只需重新安装应用程序。
【解决方案2】:

正如 Xan 所建议的,chrome.identity API 可能是您的最佳选择。您可以获取用户的电子邮件地址并将其用作随机种子来生成您选择的代码。用户信息还包括一个“id”字段,我认为它是独一无二的,但我从未见过任何证明这一点的文档。然后,您可以使用 chrome.storage.sync API 将生成的密钥存储在您应用的用户在线数据存储中。这样,用户无论何时何地在任何设备上登录,都可以访问他们的私钥。

请注意,您必须在开发者控制台中为您的应用启用 oAuth2 api,并在您的应用清单中包含应用密钥和适当的范围。

这是一个粗略的例子:

function getUserInfo (interactive, callback )
{
    var xmlhttp = new XMLHttpRequest();
    var retry = true;
    var access_token;

    getToken();

    /**
     * Request the Auth Token
     */
    function getToken()
    {       
        chrome.identity.getAuthToken( { 'interactive': interactive }, function (token) {
            if ( chrome.runtime.lastError )
            {
                console.log( "ERROR! " + chrome.runtime.lastError.message );
                return;
            }
            if ( typeof token != 'undefined ')
            {
                access_token = token;
                sendRequest( );
            }
            else
                callback( );
        });

    }

    function sendRequest()
    {       
        xmlhttp.open('GET', 'https://www.googleapis.com/userinfo/v2/me' );
        xmlhttp.setRequestHeader('Authorization','Bearer ' + access_token );
        xmlhttp.onload = requestComplete;
        xmlhttp.send();
    }

    function requestComplete()
    {
        if ( this.status == 401 && retry )
        {
            retry = false; // only retry once
            console.log( "Request failed, retrying... " + this.response );
        }
        else
        {
            console.log( "Request completed. User Info: " + this.response );
            callback(null, this.status, this.response );
            var userInfo = JSON.parse( this.response );
            storeUniqueKey( userInfo );

        }
    }
}

function storeUniqueKey( info )
{
    var key;
    // TODO: Generate some key using the user info: info.loginName
    // user info here contains several fields you might find useful.
    // There is a user "id" field here which is numeric and I believe that
    // is a unique identifier that could come in handy rather than generating your 
    // own key.

    ...

    chrome.storage.sync.set ( { user_key: key } );
}

【讨论】:

    【解决方案3】:

    添加到 Rob W 的answer。在他的方法中,保存的字符串将传播到使用相同 Google 用户帐户登录的每个 Chrome 实例 - 有很多大大小小的 if。

    如果您需要唯一标识本地用户个人资料,而不是同一 Google 用户的所有 Chrome 个人资料,您希望以相同的方式使用 chrome.storage.local。不过,这不会是唯一的 Chrome 安装标识符 - 只是该安装中的配置文件。


    还需要注意的是,所有这些数据都没有以任何方式或形式与任何事物相关联——它只是很有可能是唯一的。但绝对没有什么能阻止用户在他认为合适的时候读取和克隆这些数据。在这种情况下,您无法保护客户端。


    我认为更安全的方法是使用chrome.identity API 来请求和维护离线(因此不会过期)令牌作为许可证证明。用户无法轻松克隆此令牌存储。

    我还不精通 OAuth,所以如果有人能指出这个想法有什么问题 - 欢迎他们。

    【讨论】:

      猜你喜欢
      • 2020-08-03
      • 1970-01-01
      • 2016-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多