【问题标题】:Chrome extension doesn't send SameSite=Lax cookiesChrome 扩展不发送 SameSite=Lax cookie
【发布时间】:2019-01-14 19:21:26
【问题描述】:

我在通过弹出脚本中的 chrome 扩展处理 cookie 时遇到了一些问题。

popup.js 内容:

document.addEventListener('DOMContentLoaded', () => {
    function cookieinfo() {
        chrome.cookies.getAll({url: 'http://localhost:8080'}, function(cookie) {
            console.log('Found cookie: ', cookie)
            if (cookie == null)
                return;

            fetch('http://localhost:8080', {credentials: 'include'}).then((response) => {
                // do some stuff
                return response;
            });
        });
    }
    window.onload=cookieinfo;
}, false);

我执行的步骤:

  1. 在 localhost 上登录我的应用程序(所以我得到了 cookie)
  2. 打开弹窗(所以 popup.js 被执行)
  3. 我在控制台日志中看到 chrome 找到了必要的 cookie
  4. 服务器说传入请求的 cookie 为空
  5. 我刷新了本地应用程序的页面
  6. 我现在退出了

也许有人知道我做错了什么?

编辑:

看来原因是我的cookie有参数HttpOnly=trueSameSite=Laxrelated link)。我可以在服务器日志中看到另一个 cookie。但是由于this thread,如果credentials 参数设置为include,所有cookie 都会被发送,即使是httpOnly cookie。由于this answer,我也尝试将其发送到 127.0.0.1 而不是 localhost,结果相同。

我无法将 httpOnly 设置为 false。这是框架强制的。有人知道怎么解决吗?

编辑2:

我终于安装了Cookie编辑器,发现SameSite=Lax是原因。如果我将其设置为No Restriction,那么我将在服务器端看到它。不幸的是,我使用的框架只允许LaxStrict 选项(Chrome 扩展程序都失败了)。有谁知道如何从 Chrome 扩展发送 Lax cookie?

【问题讨论】:

  • 我会尝试 XMLHttpRequest。
  • popup.js 运行的 CPU 线程不是与浏览器主窗口运行的线程分开吗?我认为您在扩展程序的浏览器实例中设置了 cookie,但您需要在实际的浏览器窗口上下文中设置 cookie。
  • @TJBlackman 我尝试在 content.js 和 background.js 中执行此操作,结果相同。还是你的意思是另一回事?
  • @TJBlackman 看来,你是对的,因为document.cookie 返回空字符串。但是如果content_script 不是解决方案,我该如何在浏览器窗口上下文中运行代码?
  • 这是一个相关的 Chromium 错误:bugs.chromium.org/p/chromium/issues/detail?id=617198

标签: javascript cookies google-chrome-extension httponly samesite


【解决方案1】:

这是 Chromium 77 之前的扩展问题。当跨站点 cookie 设置为 SameSite=LaxSameSite=Strict 时,cookie 不会随跨站点请求一起发送。

此问题已在所有平台的版本 78 中得到修复。现在 chrome 扩展在 SameSite=LaxSameSite=Strict 时发送 cookie。

参考资料:

https://bugs.chromium.org/p/chromium/issues/detail?id=1007973

https://chromium-review.googlesource.com/c/chromium/src/+/1827503

https://bugs.chromium.org/p/chromium/issues/detail?id=617198

【讨论】:

  • 这是否意味着跨站点 cookie总是从 Chrome 扩展程序发送,而 the coming SameSite changes 实际上对扩展程序没有影响?
  • 是的,AFAIK 跨站点 cookie 总是在旧版本的 chrome 扩展中发送(当然只有当它们没有 SameSite 属性时)。这就是大多数网站 chrome 扩展使用网站 cookie 工作的方式,而无需进行太多更改。
【解决方案2】:

内容脚本是 100% 的解决方案。

您基本上有两个单独的浏览器,常规浏览器和扩展弹出浏览器。但它们是完全独立的,只能来回发送消息。因此,您需要做的是让扩展上下文向浏览器上下文发送一条消息,指示该上下文中的一些代码获取document.cookies 并将它们发送回扩展上下文。

这是我从每个独立浏览器上下文中获取cookie的示例。

manifest.json

{
  "manifest_version": 2,
  "name": "Cookie Monster",
  "description": "Nom nom nom nom",
  "version": "1.0",
  "browser_action": {
    "default_popup": "html/extension.html",
    "default_title":"Cookie Monster"
  },
  "permissions": [
    "activeTab",
    "tabs",
    "http://*/*",
    "https://*/*"
 ],
  "content_scripts": [{
    "js":["/js/client.js"],
    "matches":["http://*/*","https://*/*"]
  }]
}

extension.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Cookies</title>
    <style>
      body {
        display: block; 
        min-height: 250px; 
        width: 250px; 
        padding: 5px; 
      }
      button {
        display: block; 
        margin: 0 0 10px 0; 
      }
    </style>
  </head>
  <body class="container">
    <h1>Cookies</h1>
    <button id="extension_cookies" type="button">Get PopUp Cookies</button>
    <button id="browser_cookies" type="button">Get Browser Cookies</button>
    <p id="result"></p>

    <script src="/js/extension.js" type="text/javascript"></script>
  </body>
</html>

extension.js

'use strict';
(function(){
    // cache import DOM elements
    const extension_btn = document.querySelector('#extension_cookies');
    const browser_btn = document.querySelector('#browser_cookies'); 
    const result = document.querySelector('#result');


    // runs in the popup window of the extension, 
    // which is it's own browser context 
    // and has it's own set of cookies
    extension_btn.addEventListener('click', () => {
        if (document.cookie === ''){
            result.innerText = 'No Cookies...';
        } else {
            result.innerText = document.cookie;
        }
    })

    // send message to browser context
    // message will inform browser client of what to do
    // the browser then needs to pass data to the callback function
    // then we can display results
    browser_btn.addEventListener('click', () => {
        chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
            chrome.tabs.sendMessage(tabs[0].id, {message: 'GET_COOKIES'}, (data) => {
                result.innerText = data.cookies
            });
        });
    })
}());

client.js

'use strict';
(function(){

  // receive a callback function so I can pass data to extension
  // get document cookies, put into an object
  // use callback to send response to extension
  const get_browser_cookies = (sendResponse) => {
    const cookies = document.cookie; 
    console.clear(); 
    console.log(cookies);
    sendResponse({ cookies: cookies }); 
  }


  // listen for messages from extension
  // a switch statement can help run only the correct function
  // must pass the function a reference to the sendResponse function
  // so I can pass data back to extension
  chrome.runtime.onMessage.addListener(function(data_from_extension, sender, sendResponse){
    switch (data_from_extension.message){
      case 'GET_COOKIES': {
        get_browser_cookies(sendResponse); 
        break; 
      }
      default: null; 
    }
  });
}())

【讨论】:

  • 我试过了,没区别。我更新了问题,似乎原因是 httpOnly 标志。但是我还是不知道怎么解决
  • 我刚刚检查了 Grammarly chrome 扩展。该扩展与他们的 httponly “grauth” cookie 配合得很好,它不要求任何其他授权。所以,这是有可能的
  • 好吧,您可以检查他们的扩展代码并了解他们是如何做到的! chrisle.me/2012/12/…
  • 哇,谢谢你的技巧。但这又是我的错误。我的 cookie 有 SameSite=Lax 参数,但他们没有。所以我再次更新了问题......
  • 有人能找到解决方案吗?我已经阅读了大量的 SO 问题并尝试了多种不同的方法,但没有成功。有没有人可以解决这个问题?
【解决方案3】:

我发现 cookie 的 path 至关重要。任何不匹配都会导致误导行为。

这是我的设置:

  • 后端服务器运行在localhost:8081
  • chrome manifest 权限有"http://localhost:8081/"
  • 后端返回带有path=/ 的cookie,例如。这是一个示例响应标头Set-Cookie: refresh_token=bar; Path=/; SameSite=Lax; HttpOnly
  • chrome扩展可以手动查询cookie:chrome.cookies.get({ url: 'http://localhost:8081/', name: 'refresh_token' }...
  • 当您发送到localhost:8081下的其他url路径时,chrome扩展会自动附加cookie,例如:
    fetch('http://localhost:8081/v1/meh').then((response) => {
        console.log(response);
    })
    
    服务器端会看到refresh_token cookie。

总结一下:在路径/a 设置的cookie 不会被发送到路径/b 的url;在路径/ 设置的 cookie 将被发送到同一域下的所有 url。

【讨论】:

    猜你喜欢
    • 2022-07-05
    • 2020-06-07
    • 1970-01-01
    • 2019-10-15
    • 2021-08-21
    • 2012-06-20
    • 1970-01-01
    • 2020-12-03
    • 2016-06-03
    相关资源
    最近更新 更多