我正在开发一个在 .net Framework 4.8 上运行的旧 ASP.net MVC 应用程序。 该 Web 应用程序曾经具有自定义登录名,现在已被 Azure AD 身份验证所取代。
我设法将其设置为可以使用 Azure AD 登录到应用程序。但是,一旦我注销应用程序,我就无法再次登录,直到重新启动调试器。有趣的是,我第一次尝试重新登录时,微软登录页面在失败之前快速连续发送了许多单独的请求。
这是我在startup.cs中的设置:
public void Configuration(IAppBuilder app)
{
//added for troubleshooting
IdentityModelEventSource.ShowPII = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ConfigureAuth(app);
}
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions(){
CookieName = "blargh",
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = ConfigurationManager.AppSettings["azure:ClientId"],
Authority = $"{ConfigurationManager.AppSettings["azure:Instance"]}{ConfigurationManager.AppSettings["azure:TenantId"]}",
RedirectUri = ConfigurationManager.AppSettings["azure:RedirectUri"],
PostLogoutRedirectUri = ConfigurationManager.AppSettings["azure:PostLogoutRedirectUri"],
ClientSecret = ConfigurationManager.AppSettings["azure:ClientSecret"],
ResponseType = OpenIdConnectResponseType.IdToken,
Scope = OpenIdConnectScope.OpenIdProfile,
TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = context =>
{
using (var LoginService = new LoginService())
{
var identity = context.AuthenticationTicket.Identity;
var emailClaim = identity.FindFirst(ClaimTypes.Email)?.Value;
//omitted - some DB mapping things
return Task.CompletedTask;
}
}
},
});
这是我的注销逻辑:
public ActionResult Signout()
{
try
{
HttpContext.GetOwinContext().Authentication.SignOut(
DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.ApplicationCookie);
Session.Abandon();
var cookie = new HttpCookie("blargh")
{
Expires = DateTime.Now - TimeSpan.FromDays(1),
};
Response.Cookies.Add(cookie);
var redirectUri = Url.Action("Index", "Rapportierung", null, Request.Url.Scheme);
var logoutUrl = ConfigurationManager.AppSettings["azure:Instance"]
+ ConfigurationManager.AppSettings["azure:TenantId"]
+ "/oauth2/v2.0/logout?post_logout_redirect_uri="
+ ConfigurationManager.AppSettings["azure:PostLogoutRedirectUri"];
return Redirect(logoutUrl);
}
catch (Exception ex)
{
//omitted - Error handling
}
}
我尝试过各种小调整,例如在 TokenValidationParameters 中设置 ValidateIssuer = true、手动使 cookie 无效(如“blargh”cookie 中所示 - 仍在代码中)、更改重定向 URL、添加/删除尾随/signin-oidc 和许多其他东西。 我也尝试过清除浏览器中的所有 cookie 数据,但没有帮助。如果我切换到不同的浏览器,行为也保持不变 - 一旦我在任何浏览器中注销,登录错误也会在所有其他浏览器中发生。
任何帮助将不胜感激,我正在抓住救命稻草。 最好的问候
我在 ASP.NET Web 应用程序 4.8 中使用以下代码,利用 openid 和配置文件成功注销。
代码:
Startup.Auth.cs:
using System;
using System.Configuration;
using System.Security.Claims;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Owin;
namespace WebApplication58
{
public partial class Startup
{
private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
private static string aadInstance = EnsureTrailingSlash(ConfigurationManager.AppSettings["ida:AADInstance"]);
private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
private static string authority = aadInstance + tenantId + "/v2.0";
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
Authority = authority,
PostLogoutRedirectUri = postLogoutRedirectUri,
Scope = "openid profile",
Notifications = new OpenIdConnectAuthenticationNotifications()
{
SecurityTokenValidated = (context) =>
{
string name = context.AuthenticationTicket.Identity.FindFirst("name").Value;
context.AuthenticationTicket.Identity.AddClaim(new Claim(ClaimTypes.Name, name, string.Empty));
return System.Threading.Tasks.Task.FromResult(0);
}
}
});
}
private static string EnsureTrailingSlash(string value)
{
if (value == null)
{
value = string.Empty;
}
if (!value.EndsWith("/", StringComparison.Ordinal))
{
return value + "/";
}
return value;
}
}
}
AccountController.cs:
using System.Web;
using System.Web.Mvc;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
namespace WebApplication58.Controllers
{
public class AccountController : Controller
{
public void SignIn()
{
if (!Request.IsAuthenticated)
{
HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" },
OpenIdConnectAuthenticationDefaults.AuthenticationType);
}
}
public void SignOut()
{
string callbackUrl = Url.Action("SignOutCallback", "Account", routeValues: null, protocol: Request.Url.Scheme);
HttpContext.GetOwinContext().Authentication.SignOut(
new AuthenticationProperties { RedirectUri = callbackUrl },
OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
}
public ActionResult SignOutCallback()
{
if (Request.IsAuthenticated)
{
return RedirectToAction("Index", "Home");
}
return View();
}
}
}
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark bg-dark">
<div class="container">
@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" title="Toggle navigation" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li>@Html.ActionLink("Home", "Index", "Home", new { area = "" }, new { @class = "nav-link" })</li>
<li>@Html.ActionLink("About", "About", "Home", new { area = "" }, new { @class = "nav-link" })</li>
<li>@Html.ActionLink("Contact", "Contact", "Home", new { area = "" }, new { @class = "nav-link" })</li>
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</nav>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>
index.cshtml:
<main>
<section class="row" aria-labelledby="aspnetTitle">
<h1 id="title">Hello World</h1>
</section>
</main>
SignOutCallback.cshtml:
@{
ViewBag.Title = "Sign Out";
}
<main aria-labelledby="title">
<h2 id="title">@ViewBag.Title.</h2>
<p class="text-success">You have successfully signed out.</p>
</main>
我在Azure门户中向openid和profile授予了权限,如下所示。
输出:
我运行了上面的项目,它将我重定向到登录页面,我在其中选择了我的帐户,如下所示:
输出出现在我的帐户的浏览器中,我单击Sign Out按钮注销,如下所示:
它重定向我选择我的帐户进行注销,如下所示:
我已成功退出,如下图。