4

我有一个书签Firefox /铬WebExtension(使用标准popup,contentbackground脚本)。我的api服务器有一个/ login路由,它返回一个JSON Web Token,并且该Web应用程序将其存储在本地存储中。我完全可以控制扩展,api和网络应用程序。如何将本地存储身份验证令牌从我的网站共享到我的WebExtension?

这样做的赤脚方法是让用户通过弹出窗口登录并将身份验证令牌保存在background.js中以保存到WebExtension的本地存储中。但我真的只想要求用户在我的网站上进行身份验证,并且同样的身份验证也适用于该扩展。

有没有办法共享认证令牌?我看到Pocket和许多其他人这样做,但我不知道如何。

+0

最简单的方法很可能是发送身份验证令牌作为cookie。 – Forivin

+2

您可以使用内容脚本阅读网站的localStorage,然后通过消息将该令牌复制到背景页面localStorage中。 – wOxxOm

+0

@ wOxxOm好的方法,不知道内容脚本可以访问外部网站的本地存储。事实上,我认为本地存储比这更安全。这将需要mysite.com打开一个新标签,但这对我的用例来说是一个值得的折衷。这是相关的:https://stackoverflow.com/questions/3937000/chrome-extension-accessing-localstorage-in-content-script。 – user

回答

5

您可以将令牌存储为cookie。 Cookie的工作方式类似于localStorage,但额外的是,默认情况下,Cookie也会包装到服务器的每个HTTP请求中。诀窍来了。 Chrome扩展程序可以访问HTTP请求,并使用webRequest API。因此它可以查看请求头并知道你的cookies。将该Web令牌作为Cookie使其可用于扩展。

但仍然需要等待用户打开您的网站才能让HTTP请求流动并准备好被偷窥,对吗?不是真的。您可以直接从扩展中发出ajax请求。

下面就来说明整个事情将如何工作:

清单:

"permissions": [ 
      "webRequest", 
      "webRequestBlocking", 
      "*://*.my_site.com/*" 
     ] 

背景页:

function callback (details) { 
    // 
    token = func_extract_token_from_headers(details.requestHeaders); 

    chrome.webRequest.onBeforeSendHeaders.removeListener(callback); 

    return {cancel: false} //  set to true to prevent the request 
          // from reaching the server 
} 
chrome.webRequest.onBeforeSendHeaders.addListener (callback, 
     {urls: ["http://www.my_site.com/*", "https://www.my_site.com/*"]}, 
     ["blocking", "requestHeaders"]); 


var xurl = "https://www.my_site.com/"; 
var xhr = new XMLHttpRequest(); 
xhr.open("GET", xurl, true); 
xhr.send(); 

我应该指出,有一个更清洁的方式做到这一点,但由于CSP - 内容安全策略,它目前无法使用。正如wOxxOm在评论中提到的那样,在后台页面内的iframe中打开网站应该可以正常工作,并将CSP列入白名单。这种方法也可以避免提示用户输入凭据,并且会更干净。不幸的是它的not currently working

编辑:

对不起,我错了我的最后一个要求:在打开外部页面的I帧被阻挡在后台页面。要将其显示在后台页面(或针对该事件的弹出窗口)中,只需将CSP列入白名单,如下所示。

除了在iframe中打开页面的业务之外,您还需要与之通信。

清单:

// Whitelist your website 
    "content_security_policy": "script-src 'self' https://my_site.com/; object-src 'self'" 
// Have the background declared as html 
    "background": { "page": "background.html"} 

背景:

window.addEventListener("message", receiveMessage, false); 

function receiveMessage(event) 
{ 
    if(event.origin == "https://my_site.com"); // you may want to check the 
              // origin to be your site 
    chrome.storage.storage.local.set({'auth_token': event.data}); // the token 
} 

iframe = document.createElement('iframe'); 
iframe.src = "https://my_site.com/"; 
// Have a div ready to place iframe in 
document.getElementById('div').appendChild(iframe); 

iframe.contentWindow.postMessage("give_token", "https://my_site.com") 

的应该在使用本window.postMessage API

下面就来举例说明这一切是如何应该团结起来做网页:

window.addEventListener("message", receiveMessage, false); 

function receiveMessage(event) 
{ 
    if(event.origin == "your_extension_id_aeiou12345"); 
    event.source.postMessage(''+localStorage.auth_token, event.origin); 
} 

编辑:

此外,为了具有在iframe网站显示,确保X-frame-options响应头没有被设置为一个阻塞值。您可以将其删除,也可以将其设置为非阻止值,或者将该扩展程序的网址白名单。

+0

好方法。在我的特殊情况下,我已经在本地存储中拥有令牌,而不是cookie。我可以开始使用cookie,但我认为经过一些修改,您的答案也可以用于本地存储。这只取决于我后台的iframe是否允许访问本地存储。 – user

+1

@user iframes允许访问localStorage,但前提是iframe没有指定沙箱属性。如果添加了该属性,请确保添加了以下2个值: