如何在Tampermonkey脚本中借助已有域认证从GCS拉取文件?
解决Tampermonkey脚本拉取带域权限GCS文件的认证问题
这问题我之前帮团队里的人处理过类似场景——核心就是要拿到浏览器里已有的Google OAuth令牌,直接在请求里带上,跳过那些脚本没法自动跟进的302重定向。毕竟用户已经在当前会话完成了域内认证,咱们完全不用重新走一遍授权流程。
第一步:获取用户已有的Google Access Token
因为用户已经通过域账号登录了Google服务,浏览器里存着有效的会话令牌。我们可以借助Google的Auth客户端库来获取这个令牌,代码如下:
async function getGoogleAuthToken() { // 如果页面还没加载Google Auth库,先动态注入 if (!window.gapi) { await new Promise((resolve) => { const script = document.createElement('script'); script.src = 'https://apis.google.com/js/api.js'; script.onload = resolve; document.head.appendChild(script); }); } // 加载并初始化Auth2模块 await new Promise((resolve) => { window.gapi.load('auth2', resolve); }); // 这里的client_id要填你域内注册的OAuth客户端ID,必须和GCS权限配置匹配 const auth2 = await window.gapi.auth2.init({ client_id: '你的域OAuth客户端ID', scope: 'https://www.googleapis.com/auth/devstorage.read_only' }); // 获取当前登录用户的认证令牌 const user = auth2.currentUser.get(); const authResponse = user.getAuthResponse(); if (!authResponse.access_token) { throw new Error('未找到有效认证令牌,请刷新页面重试'); } return authResponse.access_token; }
第二步:用令牌请求GCS文件
拿到令牌后,直接在请求头里带上Authorization: Bearer {token},这样GCS会直接验证令牌有效性,不会返回302重定向。你可以用原生fetch或者Tampermonkey专属的GM_xmlhttpRequest(后者更适配用户脚本场景):
用GM_xmlhttpRequest实现:
async function fetchGCSFile(gcsFileUrl) { try { const token = await getGoogleAuthToken(); return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: gcsFileUrl, headers: { 'Authorization': `Bearer ${token}` }, onload: (res) => { if (res.status === 200) { resolve(res.responseText); // 按需改成Blob/JSON等格式 } else { reject(new Error(`请求失败:${res.statusText}`)); } }, onerror: (err) => reject(err) }); }); } catch (err) { console.error('获取GCS文件出错:', err); throw err; } }
关键注意事项
- 客户端ID匹配:你用的OAuth客户端ID必须是在你的域下注册的,并且GCS Bucket的权限已经设置了
Domain:Reader给你的域,同时客户端ID的授权域要包含当前运行脚本的网站。 - 会话过期处理:如果用户的Google会话过期,
getGoogleAuthToken会抛出错误,这时候可以提示用户刷新页面(因为用户属于域内,刷新后会自动重新认证)。 - 为什么直接请求不行:Tampermonkey的跨域请求默认不会自动处理Google OAuth的重定向(涉及accounts.google.com等第三方域),而手动带上令牌就绕开了这个问题,直接完成认证。
调用示例
在你的用户脚本里直接调用即可:
// 替换成你的GCS文件URL const gcsUrl = 'https://storage.googleapis.com/your-bucket/your-script-update.js'; fetchGCSFile(gcsUrl).then((fileContent) => { // 处理拉取到的文件内容,比如更新脚本逻辑 console.log('获取到更新内容:', fileContent); }).catch((err) => { console.error('更新失败:', err); });
内容的提问来源于stack exchange,提问作者Austin Arrowsmith
相关产品推荐
相关产品推荐

