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

ASP.NET Core认证成功后重定向至原请求端点的实现问题

解决ASP.NET Core外部登录后返回原请求端点的问题

核心逻辑

Cookie认证中间件拦截未认证请求时,会自动将原请求路径以returnUrl参数附加到登录地址。只需在登录流程中传递该参数,最终在回调完成后重定向回原地址即可实现需求。

步骤1:修改Signin方法传递ReturnUrl

更新AccountController的Signin方法,接收returnUrl并将其传入外部认证配置:

[AllowAnonymous]
[HttpGet("signin")]
public IActionResult Signin(string returnUrl = null)
{
    var callbackUrl = Url.Action(nameof(Callback), "Account", new { returnUrl });
    var props = _signInManager.ConfigureExternalAuthenticationProperties(
        GoogleDefaults.AuthenticationScheme,
        callbackUrl
    );
    return new ChallengeResult(GoogleDefaults.AuthenticationScheme, props);
}

此步骤确保Google登录完成后跳转回Callback时,能携带原请求的路径参数。

步骤2:修改Callback方法完成登录并重定向

在Callback中完成用户登录逻辑后,验证returnUrl合法性并跳转回原端点:

[AllowAnonymous]
[HttpGet("callback")]
public async Task<IActionResult> Callback(string returnUrl = null)
{
    var loginInfo = await _signInManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        // 登录失败时的默认跳转,可根据业务调整
        return RedirectToAction("Index", "Home");
    }

    // 先检查用户是否已存在,避免重复创建
    var email = loginInfo.Principal.FindFirstValue(ClaimTypes.Email);
    var user = await _userManager.FindByEmailAsync(email);
    if (user == null)
    {
        user = new User
        {
            Email = email,
            UserName = email
        };
        await _userManager.CreateAsync(user);
    }

    await _signInManager.SignInAsync(user, isPersistent: true, GoogleDefaults.AuthenticationScheme);

    // 验证地址合法性,防止开放重定向攻击
    if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
    {
        return Redirect(returnUrl);
    }
    // 默认跳转地址,可替换为业务首页
    return RedirectToAction(nameof(GetUserProfile));
}

关键注意点:必须用Url.IsLocalUrl(returnUrl)验证地址,避免恶意跳转风险。

步骤3:优化认证服务配置

调整认证配置,简化跳转流程并确保回调地址一致:

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    // 直接将默认挑战方案设为Google,减少一次跳转
    options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
    options.LoginPath = "/api/v1/account/signin";
    options.ReturnUrlParameter = "returnUrl";
})
.AddGoogle(GoogleDefaults.AuthenticationScheme, options =>
{
    options.ClientId = GetGoogleClientId();
    options.ClientSecret = GetGoogleSecret();
    // 确保此地址与控制器Callback路由一致,且已在Google开发者后台配置
    options.CallbackPath = "/api/v1/account/callback";
});

流程验证

未认证用户访问GetUserProfile时:

  1. 授权中间件拦截请求,重定向至/api/v1/account/signin?returnUrl=/api/v1/account/GetUserProfile
  2. Signin发起Google认证挑战,携带回调地址及returnUrl
  3. 用户完成Google登录后,跳转回/api/v1/account/callback?returnUrl=/api/v1/account/GetUserProfile
  4. Callback完成用户登录,验证地址后重定向回GetUserProfile
  5. 用户已认证,成功获取接口返回内容

内容的提问来源于stack exchange,提问作者Dr. Strangelove

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:25:18