首页 > 解决方案 > 如何从扩展的后台脚本在 websocket 连接中发送 cookie?

问题描述

我正在尝试从 chrome 扩展打开经过身份验证的 websocket 连接到我的后端,因为我正在使用会话 cookie。这是我的清单文件:

{
    "manifest_version": 2,
    "background": {
        "scripts": ["extension.js"],
        "persistent": true
    },
    "permissions": [
        "tabs",
        "storage",
        "http://localhost:8000/",
        "ws://localhost:8000/"
    ],
    "icons": {
        "16": "img/icon16.png",
        "48": "img/icon48.png",
        "128": "img/icon128.png"
    }
}

在那里我请求了访问localhost:8000HTTP 和 websocket 方案的权限,但 Chrome 只为 AJAX 请求发送 cookie。如果我尝试

await fetch('http://localhost:8000/checklogin', {
    method: 'GET',
    credentials: 'include'
});

从后台脚本发送cookies,但如果我尝试

const ws = new WebSocket('ws://localhost:8000/');

根本不发送任何 cookie。

不是同一个域,为什么 Chrome 不为 websocket 发送 cookie?

标签: google-chromecookiesgoogle-chrome-extensionwebsocket

解决方案


根据我的研究,我得出结论,chrome 扩展不支持带有 websocket 凭据的 CORS,因此 Chrome 不会在 websocket 升级请求中注入凭据。一种解决方法是使用chrome.webRequest拦截 websocket 升级请求并注入Cookie标头:

class WebsocketCookie {

    constructor(websocketUrl, name, value) {
        this.name = name;
        this.value = value;
        chrome.webRequest.onBeforeSendHeaders.addListener(
            ({ requestHeaders }) => {
                requestHeaders.push({name: 'Cookie', value: `${this.name}=${this.value}`});
                return {requestHeaders};
            },
            {types: ['websocket'], urls: [websocketUrl]},
            ['blocking', 'requestHeaders', 'extraHeaders']
        );
    }
}

// you can change this cookie later by changing cookie.name or cookie.value
const cookie = new WebsocketCookie('ws://localhost:8000/', 'sessionid', 'my_session_id');
const ws = new WebSocket('ws://localhost:8000/'); // sessionid cookie will be injected

这需要 websocket URL,webRequest以及webRequestBlocking要添加到清单文件的权限。使用chrome.cookies获取您需要在 websocket 升级请求中注入的 cookie。

如果您想提高安全性,onBeforeSendHeaders回调将该请求的来源作为initiator成员,使用它来检查来源是否是您自己的扩展。您可以使用chrome.management API 获取扩展程序的来源。


推荐阅读