Chrome 扩展不发送 SameSite=Lax cookie
Chrome extension doesn't send SameSite=Lax cookies
我在通过弹出脚本的 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);
我执行的步骤:
- 在本地主机上登录我的应用程序(所以我得到了 cookie)
- 打开弹窗(所以popup.js被执行)
- 我在控制台日志中看到 chrome 找到了必要的 cookies
- 服务器说传入请求的 cookie 为空
- 我刷新本地主机应用程序页面
- 我已经退出
也许有人知道我做错了什么?
编辑:
看来是因为我的cookie有参数HttpOnly=true
和SameSite=Lax
(). I can see another cookies in the server log. But due to all cookies will be sent if credentials
parameter is set to include
, even httpOnly cookies. Also I tried to send it to 127.0.0.1 instead of localhost due to this answer结果一样
我无法将 httpOnly
设置为 false。这是框架强制的。有人知道如何解决吗?
编辑2:
我终于安装了Cookie编辑器,发现是SameSite=Lax
的原因。如果我将它设置为 No Restriction
那么我将在服务器端看到它。不幸的是,我使用的框架只允许 Lax
和 Strict
选项(Chrome 扩展失败)。有谁知道如何从 Chrome 扩展程序发送 Lax cookie?
内容脚本是 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;
}
});
}())
这是 Chromium 77 版之前的扩展问题。当跨站点 cookie 设置为 SameSite=Lax
或 SameSite=Strict
时,cookie 不会随跨站点请求一起发送。
这已在所有平台的版本 78 中修复。现在 chrome 扩展在 SameSite=Lax
或 SameSite=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 的 path
很重要。任何不匹配都会导致误导行为。
这是我的设置:
- 后端服务器 运行 位于
localhost:8081
- chrome 清单权限具有
"http://localhost:8081/"
- 后端 returns cookie 与
path=/
,例如。这是一个示例响应 header 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。
我在通过弹出脚本的 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);
我执行的步骤:
- 在本地主机上登录我的应用程序(所以我得到了 cookie)
- 打开弹窗(所以popup.js被执行)
- 我在控制台日志中看到 chrome 找到了必要的 cookies
- 服务器说传入请求的 cookie 为空
- 我刷新本地主机应用程序页面
- 我已经退出
也许有人知道我做错了什么?
编辑:
看来是因为我的cookie有参数HttpOnly=true
和SameSite=Lax
(credentials
parameter is set to include
, even httpOnly cookies. Also I tried to send it to 127.0.0.1 instead of localhost due to this answer结果一样
我无法将 httpOnly
设置为 false。这是框架强制的。有人知道如何解决吗?
编辑2:
我终于安装了Cookie编辑器,发现是SameSite=Lax
的原因。如果我将它设置为 No Restriction
那么我将在服务器端看到它。不幸的是,我使用的框架只允许 Lax
和 Strict
选项(Chrome 扩展失败)。有谁知道如何从 Chrome 扩展程序发送 Lax cookie?
内容脚本是 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;
}
});
}())
这是 Chromium 77 版之前的扩展问题。当跨站点 cookie 设置为 SameSite=Lax
或 SameSite=Strict
时,cookie 不会随跨站点请求一起发送。
这已在所有平台的版本 78 中修复。现在 chrome 扩展在 SameSite=Lax
或 SameSite=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 的 path
很重要。任何不匹配都会导致误导行为。
这是我的设置:
- 后端服务器 运行 位于
localhost:8081
- chrome 清单权限具有
"http://localhost:8081/"
- 后端 returns cookie 与
path=/
,例如。这是一个示例响应 headerSet-Cookie: refresh_token=bar; Path=/; SameSite=Lax; HttpOnly
- chrome 扩展程序可以手动查询 cookie:
chrome.cookies.get({ url: 'http://localhost:8081/', name: 'refresh_token' }...
当您发送到 - chrome 扩展会自动附加 cookie,例如:
服务器端将看到fetch('http://localhost:8081/v1/meh').then((response) => { console.log(response); })
refresh_token
cookie。
localhost:8081
下的其他 url 路径时,总而言之:设置在路径 /a
的 cookie 不会发送到路径 /b
的 url;在路径 /
设置的 cookie 将被发送到同一域下的所有 url。