.NET Forms 身份验证 - 保护包含混合内容的遗留站点

.NET Forms Authentication - Securing legacy site with mixed content

我的任务是 upgrading/replacing 我们混合使用经典 asp 和 .net 应用程序的遗留站点的现有安全性。该网站一直在使用自定义 ISAPI 插件来保护页面,需要更新。

我创建了一个简单的 .net shim 应用程序并将其作为虚拟应用程序放置在站点的根目录下,位于名为 /security.

的路径中

在网站的根目录下,我创建了一个 web.config,设置如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <location allowOverride="true">
        <system.web>
            <authentication mode="Forms">
                <forms name=".APPSAUTH"
                loginUrl="Security/Authentication/"
                path="/"
                protection="All"
                requireSSL="false"
                slidingExpiration="true"
                timeout="15"/>
            </authentication>
            <authorization>
                <deny users="?"/>
            </authorization>
            <machineKey validation="SHA1"
            decryption="AES"
            validationKey="REMOVED"
            decryptionKey="REMOVED"/>
        </system.web>
    </location>
    <location path="Security">
        <system.web>
            <authorization>
                <allow users="*"/>
            </authorization>
        </system.web>
    </location>
    <system.webServer>
        <defaultDocument>
            <files>
                <clear/>
                <add value="Default.htm"/>
                <add value="Default.asp"/>
                <add value="default.aspx"/>
            </files>
        </defaultDocument>
        <modules>
            <remove name="FormsAuthentication"/>
            <add name="FormsAuthentication"
            type="System.Web.Security.FormsAuthenticationModule"
            preCondition=""/>
            <remove name="UrlAuthorization"/>
            <add name="UrlAuthorization"
            type="System.Web.Security.UrlAuthorizationModule"/>
            <remove name="DefaultAuthentication"/>
            <add name="DefaultAuthentication"
            type="System.Web.Security.DefaultAuthenticationModule"/>
        </modules>
    </system.webServer>
</configuration>

安全填充程序的 Web 配置如下所示:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
    <appSettings>
        <!-- REMOVED -->
    </appSettings>
    <system.web>
        <authentication mode="Forms">
            <forms name=".APPSAUTH"
                   loginUrl="~/Security/Authentication/"
                   path="/"
                   protection="All"
                   requireSSL="false"
                   slidingExpiration="true"
                   timeout="15"/>
        </authentication>
        <compilation debug="true"
                     targetFramework="4.7.2"/>
        <httpRuntime targetFramework="4.7.2"/>
        <machineKey validation="SHA1"
                    decryption="AES"
                    validationKey="REMOVED"
                    decryptionKey="REMOVED"/>
    </system.web>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Helpers"
                                  publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0"
                                 newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.WebPages"
                                  publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0"
                                 newVersion="3.0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Mvc"
                                  publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-5.2.7.0"
                                 newVersion="5.2.7.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    <system.codedom>
        <compilers>
            <compiler language="c#;cs;csharp"
                      extension=".cs"
                      type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                      warningLevel="4"
                      compilerOptions="/langversion:default /nowarn:1659;1699;1701"/>
            <compiler language="vb;vbs;visualbasic;vbscript"
                      extension=".vb"
                      type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                      warningLevel="4"
                      compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
        </compilers>
    </system.codedom>
</configuration>

应用程序池设置为集成模式。

就登录而言,一切正常 - 我尝试访问网站根目录下的 default.htm,我被重定向到我的安全填充程序的 signin.aspx 页面。一旦我完成身份验证过程并根据自定义用户存储验证用户,我调用

FormsAuthentication.SetAuthCookie(response.UserId, false); 设置身份验证 cookie,然后重定向到安全应用程序中的 default.aspx 页面。

default.aspx页面显示了一些简单的调试信息:

Logged in: True
User: REMOVED

使用 chrome 中的调试 window,我可以看到我正在传递身份验证 cookie:

但是,一旦我尝试访问安全文件夹之外的任何页面,我就会被重定向回安全应用程序。

在 WC3 日志中启用 cs(cookie) 后,我看到请求是通过浏览器的 auth cookie 发送的:

#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Cookie) cs(Referer) sc-status sc-substatus sc-win32-status time-taken
2021-02-24 18:53:15 SERVER_IP_ADDRESS GET /Security/Authentication/Default - 80 USERID SERVER_IP_ADDRESS Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/88.0.4324.182+Safari/537.36 .APPSAUTH=REMOVED http://SERVER_IP_ADDRESS/Security/Authentication/Callback 200 0 0 13
2021-02-24 18:53:17 SERVER_IP_ADDRESS GET / - 80 - 10.76.136.8 - - - 302 0 0 7
2021-02-24 18:53:17 SERVER_IP_ADDRESS GET / - 80 - 10.76.136.9 - - - 302 0 0 1
2021-02-24 18:53:17 SERVER_IP_ADDRESS GET /default.htm.htm - 80 - SERVER_IP_ADDRESS Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/88.0.4324.182+Safari/537.36 .APPSAUTH=REMOVED http://SERVER_IP_ADDRESS/Security/Authentication/Default 302 0 0 7
2021-02-24 18:53:17 SERVER_IP_ADDRESS GET /Security/Authentication/ ReturnUrl=%2fdefault.htm.htm 80 USERID SERVER_IP_ADDRESS Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/88.0.4324.182+Safari/537.36 .APPSAUTH=REMOVED http://SERVER_IP_ADDRESS/Security/Authentication/Default 302 0 0 8
2021-02-24 18:53:17 SERVER_IP_ADDRESS GET /Security/Authentication/Default - 80 USERID SERVER_IP_ADDRESS Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/88.0.4324.182+Safari/537.36 .APPSAUTH=REMOVED http://SERVER_IP_ADDRESS/Security/Authentication/Default 200 0 0 1

从日志中,我看到即使我的浏览器正在转发身份验证 cookie,我也会收到 302。

我错过了什么?

我发现 IIS 10 使用的模块与我的安全 mvc 应用程序使用的模块版本不同 - 我使用的是 .NET Standard 4.7.2,IIS 使用的是旧版本。

在 machineKey 标记上设置 compatibilityMode 属性允许 IIS 正确解密身份验证令牌并验证用户是否已登录:

<machineKey compatibilityMode="Framework20SP2" validation="SHA1" decryption="AES" validationKey="..." decryptionKey="..." />

启用失败的请求跟踪让我看到请求正在获取非 .NET 请求的 cookie,但身份验证令牌不能是 decrypted/validated。这最终导致我遇到了问题。