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

GSI脚本POST重定向后端后,如何携带Token跳转至React前端?

问题根源

你用GSI的data-login_uri是表单POST提交模式,浏览器会直接渲染后端返回的响应内容——所以返回Ok(token)会停在API路径,用Redirect又没法直接附加Token对象。下面给三个实用解决方案,按推荐程度排序:


方案1:前端接管谷歌登录流程(推荐,符合前后端分离架构)

放弃data-login_uri,改用前端回调处理谷歌登录结果,再通过AJAX调用后端API验证,最后自行跳转并存储Token。

前端代码调整(login.jsx)

修改GSI脚本配置,移除data-login_uri,添加data-callback指定前端回调函数:

<div id="g_id_onload"
     data-client_id="XXX"
     data-context="signin"
     data-ux_mode="popup"
     data-auto_prompt="false"
     data-callback="handleGoogleLogin"> <!-- 添加回调配置 -->
</div>
<div className="g_id_signin"
     data-type="standard"
     data-shape="rectangular"
     data-theme="outline"
     data-text="signin_with"
     data-size="large"
     data-logo_alignment="left">
</div>

<!-- 在login.jsx中定义回调函数 -->
<script>
window.handleGoogleLogin = async (response) => {
  try {
    // 把谷歌返回的credential传给后端验证
    const formData = new FormData();
    formData.append('credential', response.credential);
    
    const res = await fetch('https://localhost:44462/api/login', {
      method: 'POST',
      body: formData
    });
    
    if (!res.ok) throw new Error('验证失败');
    
    const token = await res.json();
    // 存储Token(比如localStorage或Cookie)
    localStorage.setItem('authToken', token);
    // 跳转到前端目标页面
    window.location.href = '/login';
  } catch (err) {
    console.error('登录出错:', err);
    // 这里可以添加前端错误提示UI
  }
};
</script>

后端代码调整

保持现有验证逻辑,直接返回Token即可(因为是AJAX请求,前端能拿到响应):

[ApiController]
[Route("api/")]
public class GoogleAuthController : Controller
{
    private readonly IConfiguration _config;

    // 注入配置
    public GoogleAuthController(IConfiguration config)
    {
        _config = config;
    }

    [HttpPost]
    [Route("login")]
    public async Task<IActionResult> ReturnFromApi()
    {
        var tokenid = HttpContext.Request.Form["credential"];
        GoogleJsonWebSignature.Payload payload = await GoogleJsonWebSignature.ValidateAsync(tokenid);
        
        if (!payload.Audience.Equals(_config["ClientId"]))
            return BadRequest("客户端ID不匹配");
        
        // 生成你的用户Token逻辑...
        var token = "生成的JWT或自定义Token";
        
        return Ok(token);
    }
}

方案2:后端返回自动跳转页面,携带Token

如果不想改前端GSI配置,后端可以返回一个包含跳转脚本的HTML页面,把Token存入前端存储后再跳转。

后端代码修改

替换return Ok(token)为以下代码:

public async Task<IActionResult> ReturnFromApi()
{
    // ... 原有验证逻辑 ...
    var token = "生成的用户Token";

    // 返回自动跳转的HTML页面,将Token存入localStorage
    var redirectHtml = $@"
<!DOCTYPE html>
<html>
<head>
    <meta charset='UTF-8'>
    <script>
        try {{
            localStorage.setItem('authToken', '{token}');
            window.location.href = '/login';
        }} catch (err) {{
            alert('登录失败,请重试');
            window.location.href = '/login';
        }}
    </script>
</head>
<body></body>
</html>";

    return Content(redirectHtml, "text/html");
}

注意:如果Token包含特殊字符,需要先做HTML编码,避免脚本语法错误。


方案3:用HttpOnly Cookie存储Token(同域场景适用)

如果前后端是同域名(比如用反向代理统一域名,或主域名相同),可以把Token存入HttpOnly Cookie,再跳转前端,后续请求自动携带Cookie。

后端代码修改

public async Task<IActionResult> ReturnFromApi()
{
    // ... 原有验证逻辑 ...
    var token = "生成的用户Token";

    // 设置HttpOnly Cookie(安全防XSS)
    Response.Cookies.Append("AuthToken", token, new CookieOptions
    {
        HttpOnly = true,
        Secure = true, // HTTPS环境下启用
        SameSite = SameSiteMode.Strict, // 防CSRF攻击
        Expires = DateTimeOffset.UtcNow.AddDays(7), // 有效期
        Path = "/" // 全站可用
    });

    return Redirect("/login");
}

前端后续发起API请求时,浏览器会自动携带这个Cookie,后端通过Request.Cookies["AuthToken"]获取并验证即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:24:55