.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=\"Web\" /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。这最终导致我遇到了问题。
我的任务是 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=\"Web\" /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。这最终导致我遇到了问题。