You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron谷歌登录提示「此浏览器或应用可能不安全」解决方案求助

问题原因

谷歌2022年起正式禁止嵌入式浏览器环境使用谷歌账号登录,仅修改userAgent已经无法绕过谷歌的浏览器环境指纹检测,同时你代码中使用的urn:ietf:wg:oauth:2.0:oob离线回调方式也已被谷歌废弃,二者共同导致了安全报错。

可行解决方案

方案一:系统默认浏览器授权+自定义协议回调(谷歌官方推荐,稳定性最高)

该方案完全符合谷歌的OAuth安全规范,不会被拦截,实现逻辑如下:

  1. 在Electron主进程中注册应用专属的自定义协议,用于接收登录回调
  2. 在谷歌云控制台的OAuth配置页,将自定义协议的回调地址添加到「授权重定向URI」列表
  3. 触发登录时调用系统默认浏览器打开授权链接,而非使用Electron内置的BrowserWindow
  4. 监听自定义协议的回调请求,提取授权码后兑换访问令牌

示例代码:

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登录(仅适合临时使用,长期存在被拦截风险)

如果必须使用内置窗口完成登录,需要同时修改浏览器指纹、替换废弃回调,实现逻辑如下:

  1. 替换废弃的oob回调为自定义的重定向地址,添加到谷歌云控制台的授权重定向URI列表
  2. 新增preload脚本抹除Electron专属的环境特征,比如navigator.webdriver标识
  3. 动态获取当前Electron对应的Chromium版本生成User-Agent,不要使用硬编码的旧版本UA
  4. 拦截窗口的重定向请求,提取授权码兑换令牌

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 03:09:03