为何Apollo Chrome插件可发GraphQL请求,自研插件却失败?
问题:自研Chrome扩展发送GraphQL查询出现认证错误,Apollo扩展却能成功
我正在开发一款Chrome扩展,用于向目标站点发送已有的GraphQL查询。
使用Apollo Chrome扩展测试时,我成功发送了查询。
但通过自研脚本发送时,却出现了认证错误:“User is not a workspace admin”。
我的查询通过chrome.scripting.executeScript调用,代码如下:
const doSomething = async () => { const query = JSON.stringify({ query: `MY QUERY` }); const response = await fetch(TARGET_URL, { headers: { 'content-type': 'application/json' }, method: 'POST', body: query, }); const responseJson = await response.json(); console.log(responseJson); return responseJson.data; }; chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { chrome.scripting.executeScript({ target: { tabId: tabs[0].id }, func: doSomething }, (result) => { console.log(result[0].result); }); }); const responseJson = await response.json(); console.log(responseJson);
我认为遗漏了某个认证步骤,但不清楚为何Apollo扩展与自研插件存在差异。
Apollo是如何执行请求的?我该如何修改脚本实现相同效果?
解答
Apollo扩展的请求逻辑
Apollo Chrome扩展发起请求时,会完全复用当前页面的浏览器上下文凭证:
- 自动携带当前域名下的所有认证会话Cookie
- 继承页面的认证相关请求头(如
Authorization、X-CSRF-Token) - 请求会被视为页面本身发起的请求,完全遵循站点的认证校验规则
修改自研脚本的方案
你的脚本核心问题是fetch未携带页面的认证凭证,按以下步骤调整即可:
1. 为fetch添加凭证配置
在fetch选项中加入credentials: 'include',自动携带当前域名的Cookie:
const response = await fetch(TARGET_URL, { headers: { 'content-type': 'application/json' }, method: 'POST', body: query, credentials: 'include' // 关键:携带页面认证Cookie });
2. 补充页面认证请求头(可选)
如果站点使用Cookie之外的认证头(如Authorization),可从页面上下文获取并添加到请求中:
const doSomething = async () => { // 从页面meta标签或已存请求中获取认证头 const authHeader = document.querySelector('meta[name="authorization"]')?.content; const query = JSON.stringify({ query: `MY QUERY` }); const headers = { 'content-type': 'application/json' }; if (authHeader) headers['Authorization'] = authHeader; const response = await fetch(TARGET_URL, { headers, method: 'POST', body: query, credentials: 'include' }); const responseJson = await response.json(); console.log(responseJson); return responseJson.data; };
3. 确保脚本运行在页面主上下文
明确指定executeScript的world参数为MAIN,确保脚本完全复用页面环境:
chrome.scripting.executeScript({ target: { tabId: tabs[0].id }, func: doSomething, world: 'MAIN' // 运行在页面主上下文,继承所有页面凭证 }, (result) => { console.log(result[0].result); });
验证步骤
- 修改后重新加载Chrome扩展
- 打开目标页面的Network面板,对比Apollo扩展和自研脚本的请求头,确认认证字段一致
- 若仍有错误,检查站点内容安全策略(CSP),确保扩展脚本执行权限被允许
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

