提问人:codeMonkey 提问时间:8/9/2023 更新时间:8/9/2023 访问量:62
.NET 4.8 Web 窗体 - IIS Express - 两个虚拟目录,一个应使用 FormsAuth,另一个应使用 WindowsAuth,但 Prinicipal 始终是 WindowsIdentity
.NET 4.8 Web Forms - IIS Express - Two Virtual Directories, One Should Use FormsAuth, Other WindowsAuth, but Prinicipal is Always WindowsIdentity
问:
我的网站在 IIS 上工作正常,但 IIS Express 失败。
tl:博士;如何在同一域下的 IIS Express 中配置两个单独的 .NET 4.8 Framework 应用程序作为虚拟目录,但一个使用 Windows 身份验证,另一个使用 Forms 身份验证?目前,Windows 身份验证正在覆盖它们。
我有一个站点/域,有两个虚拟目录,每个目录都指向不同的应用程序:
- domain.com
- virualDirectory1 (/app1windows)
- virtualDirectory2 (/app2forms)
app1windows
uses ,从 Active Directory 获取用户的标识,然后创建 Cookie。然后,此应用程序重定向到 ,读取 cookie,执行一些逻辑,然后设置一个新的 cookie,其中包含仅可用的附加信息。所有这些都很好。我什至用 .WindowsAuthentication
FormsAuthentication
/app2forms/handler.ashx
FormsAuthentication
app2forms
HttpContext.Current.User
GenericPrincipal
FormsIdentity
当尝试导航到页面并经过 . . .在这里,始终是 类型 ,尽管应为此应用程序关闭 Windows 身份验证。/app2forms
Application_AuthenticateRequest
HttpContext.Current.User.Identity
System.Security.Principal.WindowsIdentity
在我的web.config中,它非常清楚地指出:/app2forms
<system.web>
<authentication mode="Forms">
<forms cookieless="UseCookies" name="cookieName" path"/" etc. />
...
我右键单击了 的项目文件并显式设置为 。/app2forms
Windows Authentication
Disabled
在 的 .CSPROJ文件我已经设置了。app2forms
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>
我已经打开了applicationhost.config文件,并为每个虚拟目录设置了唯一的s。applicationPool
我的applicationhost.config文件中没有任何地方被启用,除了显式启用。windowsAuthentication
app1windows
我需要这些应用在其 web.config 文件中具有相同集的同一域下并发运行,否则将无法跨应用识别 cookie。machineKey
为什么/如何在任何地方看到任何类型的 WindowsIdentity?如何使一个应用识别 WindowsIdentity,而另一个应用使用 FormsIdentity?请帮忙。app2forms
答:
好吧,我没有试图与之抗争,而是决定顺其自然。我通过@dean-harding找到了这个答案,它建议在检测到时抓取表单cookie。所以这是我的解决方案:WindowsIdentity
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.User != null)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
if (HttpContext.Current.User.Identity is FormsIdentity)
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(id, roles);
}
else if (HttpContext.Current.User.Identity is WindowsIdentity)
{
var oldTicket = ExtractTicketFromCookie(HttpContext.Current, FormsAuthentication.FormsCookieName);
if (oldTicket != null && !oldTicket.Expired)
{
var ticket = oldTicket;
if (FormsAuthentication.SlidingExpiration)
{
ticket = FormsAuthentication.RenewTicketIfOld(oldTicket);
if (ticket == null)
return;
}
string userData = ticket.UserData;
string[] roles = userData.Split(',');
HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(ticket), roles);
if (ticket != oldTicket)
{
// update the cookie since we've refreshed the ticket
string cookieValue = FormsAuthentication.Encrypt(ticket);
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName] ??
new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue) { Path = ticket.CookiePath };
if (ticket.IsPersistent)
cookie.Expires = ticket.Expiration;
cookie.Value = cookieValue;
cookie.Secure = true;
cookie.SameSite = SameSiteMode.Lax;
cookie.HttpOnly = true;
if (FormsAuthentication.CookieDomain != null)
cookie.Domain = FormsAuthentication.CookieDomain;
HttpContext.Current.Response.Cookies.Remove(cookie.Name);
HttpContext.Current.Response.Cookies.Add(cookie);
}
}
}
}
}
}
private FormsAuthenticationTicket ExtractTicketFromCookie(HttpContext context, string name)
{
FormsAuthenticationTicket ticket = null;
string encryptedTicket = null;
var cookie = context.Request.Cookies[name];
if (cookie != null)
{
encryptedTicket = cookie.Value;
}
if (!string.IsNullOrEmpty(encryptedTicket))
{
try
{
ticket = FormsAuthentication.Decrypt(encryptedTicket);
}
catch
{
context.Request.Cookies.Remove(name);
}
if (ticket != null && !ticket.Expired)
{
return ticket;
}
// if the ticket is expired then remove it
context.Request.Cookies.Remove(name);
return null;
}
return ticket;
}
评论