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

Google Cloud API Error 400: redirect_uri_mismatch及Gmail API调用问题

问题分析与解决方案

核心问题

  1. redirect_uri不匹配:Web应用的OAuth2流程与桌面应用不同,redirect_uri必须与Google控制台配置严格一致,本地调试需使用正确的localhost地址格式。
  2. 代码流程错误:更新后的代码直接创建空的TokenResponse,未走Web应用的授权码获取→兑换token的完整流程,无法生成有效凭证。

步骤1:正确配置Google控制台的Redirect URI

  • 确认凭证类型为Web应用,而非桌面应用。
  • 本地调试时,redirect_uri必须使用http://localhost:端口号/回调页面路径(注意用正斜杠),例如本地运行端口为1234、回调页为authorize.aspx,则配置http://localhost:1234/authorize.aspx。
  • 配置要求:
    • 必须与代码中指定的redirect_uri完全一致,包括末尾是否带斜杠、路径大小写(Google不区分大小写,但严格匹配更稳妥)。
    • 本地调试优先使用localhost,避免IP地址导致的权限验证问题。

步骤2:Web应用正确的OAuth2授权流程(VB.NET)

Web应用需先引导用户到Google授权页面获取授权码,再用授权码兑换token,之后才能调用Gmail API。以下是修正后的完整逻辑:

1. 授权跳转逻辑(示例页面:member/create.aspx)

Protected Async Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    ' 无授权码时,跳转到Google授权页面
    If Request.QueryString("code") Is Nothing Then
        Dim flow As IAuthorizationCodeFlow = New GoogleAuthorizationCodeFlow(New GoogleAuthorizationCodeFlow.Initializer With {
            .ClientSecrets = New ClientSecrets With {
                .ClientId = "你的ClientId",
                .ClientSecret = "你的ClientSecret"
            },
            .Scopes = {GmailService.Scope.GmailSend},
            .DataStore = New FileDataStore("GmailAuthStore") ' 持久化存储token,避免重复授权
        })

        ' 生成授权跳转URL,redirect_uri需与控制台配置完全一致
        Dim authorizationUrl As String = flow.CreateAuthorizationCodeRequest("http://localhost:1234/authorize.aspx").Build()
        Response.Redirect(authorizationUrl)
    Else
        ' 有授权码时,兑换token并发送邮件
        Await DoOauthAndSendEmail("测试主题", "测试内容", "收件人邮箱")
    End If
End Sub

2. 修正后的邮件发送方法

Public Async Function DoOauthAndSendEmail(subject As String, body As String, recipients As String) As Task
    Dim fromEmail As String = ConfigurationSettings.AppSettings("ContactEmail")

    ' 构建并转换邮件格式
    Dim mailMessage As New MailMessage(fromEmail, recipients, subject, body)
    mailMessage.IsBodyHtml = True
    Dim mimeMessage As MimeMessage = MimeMessage.CreateFromMailMessage(mailMessage)
    Dim rawMessage As String = mimeMessage.ToString()

    ' 初始化授权流程
    Dim flow As IAuthorizationCodeFlow = New GoogleAuthorizationCodeFlow(New GoogleAuthorizationCodeFlow.Initializer With {
        .ClientSecrets = New ClientSecrets With {
            .ClientId = "你的ClientId",
            .ClientSecret = "你的ClientSecret"
        },
        .Scopes = {GmailService.Scope.GmailSend},
        .DataStore = New FileDataStore("GmailAuthStore")
    })

    ' 用授权码兑换token
    Dim code As String = Request.QueryString("code")
    Dim token As TokenResponse = Await flow.ExchangeCodeForTokenAsync("user", code, "http://localhost:1234/authorize.aspx", CancellationToken.None)

    ' 创建凭证并刷新过期token
    Dim credential As New UserCredential(flow, "user", token)
    If credential.Token.IsExpired(flow.Clock) Then
        Await credential.RefreshTokenAsync(CancellationToken.None)
    End If

    ' 初始化Gmail服务并发送邮件
    Dim gmail As New GmailService(New BaseClientService.Initializer() With {
        .ApplicationName = "你的应用名称",
        .HttpClientInitializer = credential
    })

    Dim request As UsersResource.MessagesResource.SendRequest = gmail.Users.Messages.Send(
        New Message With {.Raw = Base64UrlEncode(rawMessage)}, "me")
    Await request.ExecuteAsync()
End Function

' Base64Url编码辅助方法
Private Function Base64UrlEncode(input As String) As String
    Dim inputBytes As Byte() = System.Text.Encoding.UTF8.GetBytes(input)
    Return Convert.ToBase64String(inputBytes).Replace("+", "-").Replace("/", "_").TrimEnd("="c)
End Function

关键注意事项

  • Token持久化:FileDataStore会将token存储在本地文件中,后续请求可直接复用,无需重复引导用户授权。
  • 端口一致性:本地调试服务器(IIS/Visual Studio开发服务器)的端口号必须与redirect_uri中的端口一致。
  • OAuth同意屏幕配置:Google控制台中需完成OAuth同意屏幕配置,测试阶段可添加特定测试用户,避免授权限制。

内容的提问来源于stack exchange,提问作者Samra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 16:55:17