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

未授权用户登录重定向问题求助(区域与Google认证异常)

解决方案

问题1:区域内授权重定向到对应区域的登录页

当前代码硬编码了/Admin区域的处理逻辑,无法适配多区域场景,且路径拼接逻辑存在问题。需要动态识别当前请求所属区域,自动重定向到对应区域的登录页,同时保留ReturnUrl参数。

修改ConfigureApplicationCookie中的OnRedirectToLogin事件处理逻辑:

builder.Services.ConfigureApplicationCookie(options =>
{
    options.AccessDeniedPath = "/Error/AccessDenied";
    options.Cookie.Name = "sms_db";
    options.Cookie.HttpOnly = false;
    options.Cookie.SameSite = SameSiteMode.None;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
    options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
    options.SlidingExpiration = true;
    options.Events = new CookieAuthenticationEvents
    {
        OnRedirectToLogin = async redirectContext =>
        {
            // 从路由数据中获取当前请求的区域名称
            var areaName = redirectContext.HttpContext.Request.RouteValues["area"]?.ToString();
            
            if (!string.IsNullOrEmpty(areaName))
            {
                // 构造对应区域的登录路径
                var targetLoginPath = $"/{areaName}/Account/Login";
                // 拼接ReturnUrl参数
                var returnUrl = redirectContext.Request.Query[options.ReturnUrlParameter];
                if (!string.IsNullOrEmpty(returnUrl))
                {
                    targetLoginPath += $"?{options.ReturnUrlParameter}={Uri.EscapeDataString(returnUrl)}";
                }
                redirectContext.RedirectUri = targetLoginPath;
            }
            else
            {
                // 无区域时使用全局默认登录路径
                var defaultLoginPath = "/Account/Login";
                var returnUrl = redirectContext.Request.Query[options.ReturnUrlParameter];
                if (!string.IsNullOrEmpty(returnUrl))
                {
                    defaultLoginPath += $"?{options.ReturnUrlParameter}={Uri.EscapeDataString(returnUrl)}";
                }
                redirectContext.RedirectUri = defaultLoginPath;
            }
            await Task.CompletedTask;
        }
    };
});

问题2:重定向登录时自动触发谷歌认证

当前代码将DefaultChallengeScheme设置为谷歌认证方案,导致未授权访问时直接触发谷歌登录跳转。需要将默认挑战方案改回Identity的Application Cookie方案,仅在登录页通过手动操作触发谷歌认证。

修改AddAuthentication配置:

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = IdentityConstants.ApplicationScheme; // 使用Identity内置的Cookie认证方案
    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme; // 默认挑战走本地登录流程
})
.AddGoogle(options =>
{
    IConfigurationSection googleAuthNSection = config.GetSection("Authentication:Google");
    options.ClientId = googleAuthNSection["ClientId"] ?? "951287857071-jb9kljdsnckb40cgentmofbghogrb623.apps.googleusercontent.com";
    options.ClientSecret = googleAuthNSection["ClientSecret"] ?? "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";
});

注意:无需重复调用.AddCookie(),AddIdentity已经自动配置了Application Cookie认证体系。

之后在登录页添加谷歌登录按钮,手动触发认证流程:

登录页视图代码

<form asp-action="ExternalLogin" asp-route-Provider="Google" method="post">
    <button type="submit" class="btn btn-primary">使用Google登录</button>
</form>

控制器对应方法

[AllowAnonymous]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
    var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
    var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
    return Challenge(properties, provider);
}

[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    if (remoteError != null)
    {
        ModelState.AddModelError(string.Empty, $"第三方登录错误: {remoteError}");
        return View("Login");
    }
    var loginInfo = await _signInManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction(nameof(Login));
    }

    // 尝试直接登录关联账户
    var signInResult = await _signInManager.ExternalLoginSignInAsync(loginInfo.LoginProvider, loginInfo.ProviderKey, isPersistent: false, bypassTwoFactor: true);
    if (signInResult.Succeeded)
    {
        return LocalRedirect(returnUrl ?? "/");
    }
    // 处理未关联本地账户的情况,引导用户完成注册绑定
    ViewData["ReturnUrl"] = returnUrl;
    ViewData["LoginProvider"] = loginInfo.LoginProvider;
    var userEmail = loginInfo.Principal.FindFirstValue(ClaimTypes.Email);
    return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = userEmail });
}

修改后,未授权访问会先跳转至对应区域的登录页,用户可自主选择本地登录或触发谷歌认证。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:44:59