.NET Framework 4.8集成Azure AD登出重登无限循环问题求助
Azure AD登出后重新登录无限循环问题(.NET Framework 4.8)
我有一个基于.NET Framework 4.8构建的Web应用,已集成Azure AD登录功能。当登出后尝试重新登录时,会进入对Microsoft的调用无限循环,直至出现访问失败错误。已尝试网上各类解决方案,但均未生效。
启动代码
public void Configuration(IAppBuilder app) { string cookieDays = ConfigurationManager.AppSettings["cookieDays"]; string clientId = ConfigurationManager.AppSettings["ClientId"]; string authority = ConfigurationManager.AppSettings["Authority"]; string redirectUri = ConfigurationManager.AppSettings["redirectUri"]; string logoutRedirectUri = ConfigurationManager.AppSettings["logoutRedirectUri"]; app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationType = "Cookies", CookieSecure = CookieSecureOption.Always, ExpireTimeSpan = TimeSpan.FromDays(int.Parse(cookieDays)) }); app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // Sets the client ID, authority, and redirect URI as obtained from Web.config ClientId = clientId, Authority = authority, RedirectUri = redirectUri, // PostLogoutRedirectUri is the page that users will be redirected to after sign-out. In this case, it's using the home page PostLogoutRedirectUri = logoutRedirectUri, Scope = OpenIdConnectScope.OpenIdProfile, // ResponseType is set to request the code id_token, which contains basic information about the signed-in user ResponseType = OpenIdConnectResponseType.CodeIdToken, // ValidateIssuer set to false to allow personal and work accounts from any organization to sign in to your application // To only allow users from a single organization, set ValidateIssuer to true and the 'tenant' setting in Web.config to the tenant name // To allow users from only a list of specific organizations, set ValidateIssuer to true and use the ValidIssuers parameter TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = false // Simplification (see note below) } } ); }
LoginController代码
[Authorize] public ActionResult Auth() { var userClaims = User.Identity as System.Security.Claims.ClaimsIdentity; string email = userClaims?.FindFirst("preferred_username")?.Value; using (var entities = new SqlProdDbContext()) { Utenti user = entities.Utenti.Where(u => u.Email == email).SingleOrDefault(); if (user == null) { Users temp = new Users(); temp.LoginErrorMessage = "Utente non valido"; return View("Index", temp); } } Session["userName"] = userClaims?.FindFirst("name")?.Value; Session["UserEmail"] = userClaims?.FindFirst("preferred_username")?.Value; Session["Roles"] = "1"; Session["name"] = userClaims?.FindFirst("preferred_username")?.Value.Split('@')[0]; return RedirectToAction("Index", "Home"); } public void SignOut() { HttpContext.GetOwinContext().Authentication.SignOut(); HttpContext.Response.AddHeader("Cache-Control", "no-cache, no-store, must-revalidate"); HttpContext.Response.AddHeader("Pragma", "no-cache"); HttpContext.Response.AddHeader("Expires", "0"); HttpContext.Response.Redirect("/"); } public ActionResult ClearSession() { HttpContext.Session.Clear(); //Session.Clear(); Session.Abandon(); Request.GetOwinContext().Authentication.SignOut(); Request.GetOwinContext().Authentication.SignOut(Microsoft.AspNet.Identity.DefaultAuthenticationTypes.ApplicationCookie); this.HttpContext.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); return RedirectToAction("Index"); }
问题修复方案
1. 统一Cookie认证类型
启动代码中SetDefaultSignInAsAuthenticationType使用默认值CookieAuthenticationDefaults.AuthenticationType,但UseCookieAuthentication的AuthenticationType设为了"Cookies",两者不匹配会导致身份验证流程混乱。修改Cookie认证配置:
app.UseCookieAuthentication(new CookieAuthenticationOptions() { AuthenticationType = CookieAuthenticationDefaults.AuthenticationType, // 与默认登录类型一致 CookieSecure = CookieSecureOption.Always, ExpireTimeSpan = TimeSpan.FromDays(int.Parse(cookieDays)) });
2. 完善登出逻辑
当前登出方法未完整触发Azure AD端的会话注销,仅清理本地Cookie会导致云端会话残留,引发循环。修改SignOut方法:
public void SignOut() { // 指定要注销的认证类型:Cookie和OpenIdConnect var authTypes = new[] { CookieAuthenticationDefaults.AuthenticationType, OpenIdConnectAuthenticationDefaults.AuthenticationType }; HttpContext.GetOwinContext().Authentication.SignOut(authTypes); // 禁用缓存,避免浏览器加载旧会话页面 HttpContext.Response.AddHeader("Cache-Control", "no-cache, no-store, must-revalidate"); HttpContext.Response.AddHeader("Pragma", "no-cache"); HttpContext.Response.AddHeader("Expires", "0"); // 跳转到配置的登出回调地址,而非直接根目录 var logoutRedirectUri = ConfigurationManager.AppSettings["logoutRedirectUri"]; HttpContext.Response.Redirect(logoutRedirectUri); }
3. 添加OpenIdConnect登出通知处理
在OpenIdConnect配置中添加通知,确保登出时传递正确的id_token_hint和回调地址,避免流程异常:
app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { // 原有配置... Notifications = new OpenIdConnectAuthenticationNotifications { RedirectToIdentityProvider = n => { if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout) { // 传递id_token_hint给Azure AD,确保正确注销 var idToken = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value; if (!string.IsNullOrEmpty(idToken)) { n.ProtocolMessage.IdTokenHint = idToken; } // 明确指定登出回调地址 n.ProtocolMessage.PostLogoutRedirectUri = ConfigurationManager.AppSettings["logoutRedirectUri"]; } return Task.FromResult(0); } } } );
4. 检查Azure AD应用注册配置
确保Web.config中的redirectUri和logoutRedirectUri已在Azure AD应用注册的:
- 重定向URI(认证->重定向URI)
- 前端通道注销URI(认证->前端通道注销URI)
中正确配置,否则会因回调地址不被信任触发流程失败,导致循环。
内容的提问来源于stack exchange,提问作者alessandro vernile
相关产品推荐
相关产品推荐

