.NET 4.8 Web 表单 - IIS Express - 两个虚拟目录,一个应该使用 FormsAuth,其他 WindowsAuth,但主体始终是 WindowsIdentity

问题描述 投票:0回答:1

我的网站在 IIS 上工作正常,但 IIS Express 失败。

tl:博士;如何在同一域下的 IIS Express 中将两个单独的 .NET 4.8 Framework 应用程序配置为虚拟目录,但一个使用 Windows Auth,另一个使用 Forms Auth?现在 Windows Auth 正在覆盖它们。

我有一个带有两个虚拟目录的站点/域,每个目录都指向不同的应用程序:

- domain.com
  - virualDirectory1 (/app1windows)
  - virtualDirectory2 (/app2forms)

app1windows
使用
WindowsAuthentication
,从 Active Directory 获取用户身份,然后创建
FormsAuthentication
cookie。然后,该应用程序重定向到
/app2forms/handler.ashx
,后者读取 cookie,执行一些逻辑,然后设置一个新的
FormsAuthentication
cookie,其中仅包含
app2forms
中可用的附加信息。所有这些都运行良好。我什至将
HttpContext.Current.User
设置为新的
GenericPrincipal
FormsIdentity

/app2forms
然后尝试导航到页面并经过
Application_AuthenticateRequest
时,就会出现问题。 。 。在这里,
HttpContext.Current.User.Identity
始终是
System.Security.Principal.WindowsIdentity
类型,尽管事实上应该为此应用程序关闭Windows身份验证。

在我的

/app2forms
的 web.config 中,它非常清楚地指出:

<system.web>
    <authentication mode="Forms">
        <forms cookieless="UseCookies" name="cookieName" path"/" etc. />
...

我右键单击了

/app2forms
的项目文件,并将
Windows Authentication
显式设置为
Disabled

app2forms
的 .CSPROJ 文件中,我设置了
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>

我已打开 applicationhost.config 文件并为每个虚拟目录设置唯一的

applicationPool

除了明确的

windowsAuthentication
之外,我的 applicationhost.config 文件中没有任何地方启用了
app1windows

我需要这些应用程序在同一域下同时运行,并在其 web.config 文件中设置相同的

machineKey
,否则 cookie 将无法跨应用程序识别。

为什么/如何

app2forms
在任何地方看到任何类型的 WindowsIdentity?如何让一个应用程序识别 WindowsIdentity,而另一个应用程序使用 FormsIdentity?请帮忙。

c# .net webforms forms-authentication iis-express
1个回答
0
投票

好吧,我决定顺其自然,而不是试图与之抗争。我发现@dean-harding 的这个答案建议在检测到

WindowsIdentity
时抓取表单cookie。所以这是我的解决方案:

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.