未授权用户登录重定向问题求助(区域与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
相关产品推荐
相关产品推荐

