使用MVC和ASP.NET身份验证进行URL授权

14

我想保护我的应用程序中特定文件夹和资源,这些资源不在mvc应用程序的路由之内。我希望这些资源只对已验证的用户(角色不重要,只要他们经过身份验证)可用。

最初似乎UrlAuthorizationModule是答案。我按照这篇文章Understanding IIS 7.0 URL Authorization操作,我可以使模块根据web.config中的配置元素工作。

我的问题是我认为它基于IIS中的匿名用户而不是asp.net身份验证的验证用户实施规则。

测试环境

我使用标准的html文件进行测试,而不是尝试加载脚本,因为这也将在MVC管道之外加载。

  • Visual Studio 2015中。
    • 新建默认的.net 4.6.2 web项目
    • MVC 模板
    • 身份验证= 单个用户帐户
  • IIS 8(用于在Visual Studio之外测试
    • 认证->匿名身份验证(启用)

添加到 web.config

<configuration>
...
<location path="Data">
  <system.webServer>
    <security>
      <authorization>
        <clear/>
        <add accessType="Deny" users="*"/>
        <add accessType="Allow" users="?"/>
      </authorization>
    </security>
  </system.webServer>
</location>
...
</configuration>

添加到文件夹结构

/Data/Protected.html // this file just has some basic Hello World content to display so you can see if it is loaded or not.

观察结果

  • 使用此配置会始终拒绝Data路径中的所有内容,无论用户是否已通过身份验证。
  • 如果我在web.config中切换DenyAllow的2行,则情况也是如此。
  • 如果我完全删除带有Deny的行,则即使用户未通过身份验证,也将始终允许访问。
  • 如果我添加一个角色并使用角色名称的roles属性而不是users属性,则该角色也将被完全忽略。

现在怎么办?

我错过了什么?我如何在MVC/WebAPI和ASP.NET IdentityIndividual user accounts上使用Url Authorization模块,或这根本做不到吗?

我也可以接受其他想法,也许答案是编写自定义HttpModuleHttpHandler


附注

为什么和细节

这些资源是JavaScript文件,简而言之,只有未经身份验证的用户才能使用其中的一部分脚本。根目录中有两个目录,一个用于应用程序的已验证部分,另一个用于非验证部分。这样做的原因与用户授权或应用程序安全性无关,它旨在将应用程序的暴露表面限制为非身份验证请求。


我对URL授权模块没有经验,但如果您使用HttpModule,您可以在“AuthorizeRequest”事件阶段检查用户是否已经过身份验证以及他想要访问哪个路径... - Legends
@Legends - 我最初尝试使用 HttpModule,但在尝试与 Asp.net Identity 集成时遇到了麻烦。而且我希望不必重新发明轮子。 - Igor
250赏金,我相信会有人回答的... - Legends
@Legends - 是的,我考虑了所有这些。我还在上面添加了重现问题的步骤,这对于任何版本的VS2015都是可能的(可能需要5分钟)。 - Igor
你能告诉我为什么我添加了 HtmlScriptHandler 处理程序吗?:-) 因为 URL 授权在没有它的情况下也可以工作。我记得以前有问题,但现在我无法再现任何问题... 所以,在完整的 web.config 示例中注释掉此处理程序,在我的情况下可以正确处理 URL 授权。 - Legends
显示剩余4条评论
1个回答

13

[简而言之;]
请前往"完整的根 web.config"部分查看所需的web.config设置。

在隐身模式下测试以防止浏览器缓存问题! 并使用Ctrl+F5,因为脚本和HTML文件会被缓存。

首先,在根web.config中拒绝所有匿名用户的访问。

<authorization>
    <deny users="?"/>        
</authorization>

这里的web.config允许一个文件夹被公开访问。在我的示例中,此文件夹名为 css ,位于MVC应用程序的根目录中。对于css文件夹,我在根web.config中添加了以下授权:

<location path="css">
    <system.web>
        <authorization>          
            <allow users="*"/>
        </authorization>
    </system.web>
</location>

如果您想要更多的公共文件夹,可以添加更多这些位置路径。

当用户未登录时,所有其他文件都将无法访问,但css文件夹及其内容始终可访问。

我还在根web.config中添加了一个静态文件处理程序,这非常重要,因为您希望特定文件类型的请求由asp.net管道管理

<handlers>
    <add name="HtmlScriptHandler" path="*.html" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler" />
</handlers> 

完整的根web.config

<system.web>
    <authentication mode="None" />
    <authorization>
        <deny users="?"/>        
    </authorization>
    <compilation debug="true" targetFramework="4.6.2" />
    <httpRuntime targetFramework="4.6.2" />
</system.web>
<location path="css">
    <system.web>
        <authorization>          
            <allow users="*"/>
        </authorization>
    </system.web>
</location>
<system.webServer>
    <modules>
        <remove name="FormsAuthentication" />           
        <remove  name="UrlAuthorization" />
        <add  name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule"  />     
    </modules>
    <handlers>
        <add name="HtmlScriptHandler" path="*.html" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler" />
    </handlers>      
</system.webServer>

ASP.NET默认仅对由托管处理程序处理的文件应用允许和拒绝规则。静态文件不受托管处理程序管理。

您还可以设置:(如果不是真正需要,请勿这样做!

 <modules runAllManagedModulesForAllRequests="true">

使用 runAllManagedModulesForAllRequests="true",所有HTTP模块都会在每个请求上运行,而不仅仅是托管请求(例如 .aspx, ashx)。这意味着模块将在每个 .jpg ,.gif ,.css ,.html ,.pdf 等任何请求上运行。


一个重要的事情
您不必将UrlAuthorizationModule添加到模块部分,因为它已经是ASP.NET管道的一部分。这意味着它仅适用于托管文件,而不是静态文件!

如果您现在从模块部分中删除然后重新添加UrlAuthorizationModule,则它将在“integratedMode”预条件下运行,而不再是在“managedHandler”下运行!因此,它将可以访问静态文件。

<remove  name="UrlAuthorization" />
<add  name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />


如果您将前置条件设置为managed: <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />,那么UrlAuthorizationModule将不再限制对静态文件的访问。

您可以通过成功访问脚本文件夹中的脚本文件来测试此功能,同时退出登录。按Ctrl+F5以确保您获取脚本文件的最新副本。


ASP.NET UrlAuthorization与IIS URL Authorization的区别

重要的是要记住,managedHandler预条件适用于ASP.NET UrlAuthorization模块。该预条件告诉您,只有在处理请求的代码映射到托管代码时(通常是.aspx或.asmx页面),才会调用URL授权模块。另一方面,IIS URL Authorization适用于所有内容。您可以从ASP.NET Url Authorization模块中删除managedHandler预条件。它存在的目的是防止每个请求(例如对.html或.jpg页面的请求)都必须经过托管代码,以避免性能损失。

P.S.:某些web.config属性区分大小写!


1
谢谢,使用您的解决方案,我一直在倒推,直到我得到了我需要让它工作的更改。我将编辑您的帖子,请在我完成后进一步编辑它。 - Igor
1
所以我缺少的部分,也是为什么“授权”元素从未生效的原因是因为我没有为受限文件类型注册“HttpHandler”。一旦我添加了这个并且在“system.web”元素中使用了“authorization”元素,一切都按预期工作了。再次感谢。 - Igor
我很高兴它有帮助;-) - Legends
1
不错的更新(250声望,非常值得!)- 请注意:在这种情况下,FormsAuthentication模块未启用,因为正在使用aps.net身份验证/授权框架。我已经在我的网站上运行它,对于FormsAuthentication的唯一引用是要删除它的一行项目。 - Igor
我已经删除了添加并保留了删除:D - Legends

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接