Electron谷歌登录提示「此浏览器或应用可能不安全」解决方案求助
问题原因
谷歌2022年起正式禁止嵌入式浏览器环境使用谷歌账号登录,仅修改userAgent已经无法绕过谷歌的浏览器环境指纹检测,同时你代码中使用的urn:ietf:wg:oauth:2.0:oob离线回调方式也已被谷歌废弃,二者共同导致了安全报错。
可行解决方案
方案一:系统默认浏览器授权+自定义协议回调(谷歌官方推荐,稳定性最高)
该方案完全符合谷歌的OAuth安全规范,不会被拦截,实现逻辑如下:
- 在Electron主进程中注册应用专属的自定义协议,用于接收登录回调
- 在谷歌云控制台的OAuth配置页,将自定义协议的回调地址添加到「授权重定向URI」列表
- 触发登录时调用系统默认浏览器打开授权链接,而非使用Electron内置的BrowserWindow
- 监听自定义协议的回调请求,提取授权码后兑换访问令牌
示例代码:
const { app, shell } = require('electron') const { google } = require('googleapis') const path = require('path') // 注册自定义协议(需在app ready前执行,示例协议名为yourapp,可自行修改) if (process.defaultApp) { if (process.argv.length >= 2) { app.setAsDefaultProtocolClient('yourapp', process.execPath, [path.resolve(process.argv[1])]) } } else { app.setAsDefaultProtocolClient('yourapp') } // OAuth配置,redirectUri需和谷歌云控制台配置完全一致 const clientId = '你的谷歌应用ClientID' const clientSecret = '你的谷歌应用ClientSecret' const redirectUri = 'yourapp://oauth-callback' const oauth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri) // 触发谷歌登录的逻辑 function startGoogleLogin() { const authUrl = oauth2Client.generateAuthUrl({ access_type: 'offline', scope: scopes // 替换为你需要的权限列表 }) shell.openExternal(authUrl) } // 监听自定义协议回调,处理登录结果 app.on('open-url', (event, url) => { event.preventDefault() const authCode = new URL(url).searchParams.get('code') if (!authCode) return // 用授权码兑换访问令牌 oauth2Client.getToken(authCode, (err, tokens) => { if (err) { console.error('登录失败:', err) return } oauth2Client.setCredentials(tokens) // 此处添加登录成功后的业务逻辑 console.log('登录成功,令牌信息:', tokens) }) })
方案二:内置BrowserWindow登录(仅适合临时使用,长期存在被拦截风险)
如果必须使用内置窗口完成登录,需要同时修改浏览器指纹、替换废弃回调,实现逻辑如下:
- 替换废弃的oob回调为自定义的重定向地址,添加到谷歌云控制台的授权重定向URI列表
- 新增preload脚本抹除Electron专属的环境特征,比如
navigator.webdriver标识 - 动态获取当前Electron对应的Chromium版本生成User-Agent,不要使用硬编码的旧版本UA
- 拦截窗口的重定向请求,提取授权码兑换令牌
preload.js示例代码:
// 抹除谷歌会检测的嵌入式浏览器标识 Object.defineProperty(navigator, 'webdriver', { get: () => undefined }) // 移除Electron专属全局变量 delete window.ELECTRON_ENABLE_SECURITY_WARNINGS delete window.ELECTRON_DISABLE_SECURITY_WARNINGS
主进程示例代码:
const { app, BrowserWindow } = require('electron') const { google } = require('googleapis') const path = require('path') const clientId = '你的谷歌应用ClientID' const clientSecret = '你的谷歌应用ClientSecret' const redirectUri = 'https://localhost/oauth-callback' // 无需实际部署,仅用于拦截回调 const oauth2Client = new google.auth.OAuth2(clientId, clientSecret, redirectUri) function startGoogleLogin() { const win = new BrowserWindow({ height: 600, width: 800, webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, sandbox: true, enableRemoteModule: false } }) const authUrl = oauth2Client.generateAuthUrl({ access_type: 'offline', scope: scopes // 替换为你需要的权限列表 }) // 动态生成和当前Electron匹配的UA,避免硬编码旧版本 const userAgent = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${process.versions.chrome} Safari/537.36` win.loadURL(authUrl, { userAgent }) // 拦截重定向请求提取授权码 win.webContents.on('will-redirect', (event, redirectUrl) => { if (redirectUrl.startsWith(redirectUri)) { event.preventDefault() const authCode = new URL(redirectUrl).searchParams.get('code') if (!authCode) return oauth2Client.getToken(authCode, (err, tokens) => { if (err) { console.error('登录失败:', err) return } oauth2Client.setCredentials(tokens) // 此处添加登录成功后的业务逻辑 console.log('登录成功,令牌信息:', tokens) win.close() }) } }) }
注意事项
- 优先使用方案一,方案二依赖当前谷歌的检测规则,后续规则更新后可能再次失效
- 所有使用到的重定向地址必须提前在谷歌云控制台的OAuth配置中添加到授权重定向URI列表,否则会触发权限报错
- 若使用方案二,需确保Electron版本保持更新,避免使用过于老旧的Chromium内核
内容的提问来源于stack exchange,提问作者cuuupid
相关产品推荐
相关产品推荐

