如何在Ruby on Rails应用中无OOB_URI使用Google Sheets API?
解决Google Sheets API OOB流禁用问题(Ruby on Rails)
Google已全面禁用OOB(urn:ietf:wg:oauth:2.0:oob)授权流,以下是针对你的「永久访问、频繁调用API」需求的两种解决方案,优先推荐服务账号方案。
方案一:服务账号认证(推荐,无用户交互、永久访问)
服务账号是Google Cloud专为服务器端应用设计的认证方式,无需用户手动授权,令牌自动刷新,完美适配后台持续调用API的场景。
1. 配置服务账号
- 登录Google Cloud Console,进入你的项目,前往「IAM与管理」→「服务账号」,创建新服务账号。
- 生成密钥:在服务账号详情页的「密钥」标签下,点击「添加密钥」→「创建新密钥」,选择JSON格式,下载后保存到
config/google_service_account_key.json。 - 共享目标Google Sheet:将服务账号邮箱(密钥JSON中的
client_email字段)添加为表格的「查看者」(如需编辑权限则设为「编辑者」)。
2. 修改代码
替换原有的authorize方法,改用服务账号认证:
require 'google/apis/sheets_v4' require "googleauth" APPLICATION_NAME = "Google Sheets API Ruby App".freeze SERVICE_ACCOUNT_KEY_PATH = "config/google_service_account_key.json".freeze SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS_READONLY def authorize # 从服务账号密钥文件初始化认证 credentials = Google::Auth::ServiceAccountCredentials.make_creds( json_key_io: File.open(SERVICE_ACCOUNT_KEY_PATH), scope: SCOPE ) credentials.fetch_access_token! credentials end def datasheets service = Google::Apis::SheetsV4::SheetsService.new service.client_options.application_name = APPLICATION_NAME service.authorization = authorize spreadsheet_id = "你的目标表格ID" range = "Class Data!A2:E" response = service.get_spreadsheet_values spreadsheet_id, range puts "Name, Major:" response.values.empty? ? puts("No data found.") : response.values.each { |row| puts "#{row[0]}, #{row[4]}" } end
3. Gemfile保持不变
gem 'googleauth' gem 'google-api-client' gem 'google-apis-sheets_v4'
方案二:用户授权替代流(需用户交互)
如果必须关联特定用户账号,可选择以下两种替代OOB的授权方式:
方式1:桌面应用(本地端口重定向)
- 在Google Cloud Console的「API与服务」→「凭据」,创建「桌面应用」类型的OAuth客户端ID。
- 修改授权逻辑,使用本地端口接收回调:
require 'google/apis/sheets_v4' require "googleauth" require "googleauth/stores/file_token_store" require "webrick" APPLICATION_NAME = "Google Sheets API Ruby Quickstart".freeze CREDENTIALS_PATH = "config/google_sheets_credentials.json".freeze TOKEN_PATH = "token.yaml".freeze SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS_READONLY REDIRECT_URI = "http://localhost:3000/oauth2callback" def authorize client_id = Google::Auth::ClientId.from_file CREDENTIALS_PATH token_store = Google::Auth::Stores::FileTokenStore.new file: TOKEN_PATH authorizer = Google::Auth::UserAuthorizer.new client_id, SCOPE, token_store user_id = "default" credentials = authorizer.get_credentials user_id if credentials.nil? # 启动临时本地服务器接收授权码 server = WEBrick::HTTPServer.new(Port: 3000, BindAddress: 'localhost') code = nil server.mount_proc '/oauth2callback' do |req, res| code = req.query['code'] res.body = "授权成功!可以关闭此窗口。" server.shutdown end Thread.new { server.start } # 生成授权URL并提示用户打开 url = authorizer.get_authorization_url(base_url: REDIRECT_URI) puts "请在浏览器中打开以下链接:\n#{url}" sleep until code credentials = authorizer.get_and_store_credentials_from_code( user_id: user_id, code: code, base_url: REDIRECT_URI ) end credentials end
方式2:Web应用(服务器端重定向)
针对Rails Web应用,创建「Web应用」类型的OAuth客户端ID,配置重定向URI为https://你的域名/oauth2callback,通过Rails路由处理回调并持久化令牌(如存入数据库)。
关键注意事项
- 服务账号方案无需用户干预,令牌自动刷新,是满足「永久访问、频繁调用」需求的最优解。
- 确保服务账号邮箱已被共享到目标Google Sheet,否则会触发权限不足错误。
- 服务账号密钥文件包含敏感信息,需添加到
.gitignore,禁止提交到版本控制。
内容的提问来源于stack exchange,提问作者Elise S
相关产品推荐
相关产品推荐

