Web Deploy 高级应用:自动设置 ACL
2011-01-04 19:39 Nana's Lich 阅读(6042) 评论(0) 编辑 收藏 举报引言
前一篇文章中讲解了 Web Deploy 技术的简单使用,以及避免已有的 ACL 设置被清除的办法。
而这一次我将会讲解在使用 Visual Studio (Express) 进行一键发布时自动完成 ACL 设置的办法。
原理
在解决上一篇文章的问题的过程中中提到了 MSBuild 指令的使用,稍加思考的话并不难得出这样一个结论:
Web Deploy 设置 ACL 的具体方式也是通过 MSBuild 操控的。
而如果我们调查了 Microsoft.Web.Publishing.targets 的话,就会发现这样的一些指令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <!--Make sure the by default Networkservice/AppPoolIdentity have read permissing to the fodler--> < MsDeploySourceManifest Include="setAcl" Condition="$(IncludeSetAclProviderOnDestination)"> < Path >$(_MSDeployDirPath_FullPath)</ Path > < setAclResourceType >Directory</ setAclResourceType > < AdditionalProviderSettings >setAclResourceType</ AdditionalProviderSettings > </ MsDeploySourceManifest > <!--Make sure the by default anonymousAuthenticationUser have read permissing to the fodler so MIME type files will work--> < MsDeploySourceManifest Include="setAcl" Condition="$(IncludeSetAclProviderOnDestination)"> < Path >$(_MSDeployDirPath_FullPath)</ Path > < setAclUser >anonymousAuthenticationUser</ setAclUser > < setAclResourceType >Directory</ setAclResourceType > < AdditionalProviderSettings >setAclUser;setAclResourceType</ AdditionalProviderSettings > </ MsDeploySourceManifest > <!--Additionally if App_Data Need to be ReadWrite--> < MsDeploySourceManifest Include="setAcl" Condition="$(IncludeSetAclProviderOnDestination) And $(MarkApp_DataWritableOnDestination) And Exists('$(_MSDeployDirPath_FullPath)\App_Data')"> < Path >$(_MSDeployDirPath_FullPath)\App_Data</ Path > < setAclAccess >Write</ setAclAccess > < setAclResourceType >Directory</ setAclResourceType > < AdditionalProviderSettings >setAclResourceType;setAclAccess</ AdditionalProviderSettings > </ MsDeploySourceManifest > |
其中 XML 元素名称 MsDeploySourceManifest 表示了它会在 Web Deploy 的程序清单(Manifest)中产生一个对应的指令;
Include="setAcl" 指示了将要产生一个 setAcl 指令,顾名思义,它是用来设置 ACL 的;
Condition="..." 表示这条指令将在特定的条件下产生,由于其中涉及到了大量的其它 MSBuild 指令,现在就详细讲解似乎有点早,为了不让大家被一大堆概念搞得晕头转向,这部分放后面说;
<Path>$(_MSDeployDirPath_FullPath)</Path> 指示了将要向网站程序的根目录设置 ACL,$(_MSDeployDirPath_FullPath) 表示了 Web Deploy 的目标路径(它的实际含义其实是有些区别的,同样放后面);
<setAclAccess>Write</setAclAccess> 指示了赋予写操作的权限,如果只需要读操作权限,可以省略掉;
<setAclUser>anonymousAuthenticationUser</setAclUser> 指示了将要向谁赋予操作权限,anonymousAuthenticationUser 表示匿名访问者,如果希望向应用程序池的身份标识赋予操作权限,就可以省略掉;
<setAclResourceType>Directory</setAclResourceType> 表示将要向一个目录设置 ACL,可以省略掉;
<AdditionalProviderSettings>setAclResourceType</AdditionalProviderSettings> 表示启用 setAclResourceType 选项,如果其中不包含任何选项,就同样可以省略。
综合来说,上面所列出的这些指令说明了在默认情况下,Web Deploy 会自动赋予匿名用户及应用程序池对网站目录的读操作权限(省略时)、赋予应用程序池对数据库目录的写操作权限(看来这里不需要写成“Read,Write”,是个有意思的现象)
操练起来
如果要给应用程序池指派其它的操作权限——比方说完全控制网站目录,也需要使用像是这样的指令。
不过实际上在 *.wpp.targets 里面添加这样的 MSBuild 指令的时候是有些技术细节需要注意的,比方说这些指令应该添加在什么地方、怎么样让它们被执行。
就以这次的“完全控制”来说,首先自然要依葫芦画瓢地写一段指令,大概会是这样:
1 2 3 4 5 | < MsDeploySourceManifest Include="setAcl"> < Path >$(_MSDeployDirPath_FullPath)</ Path > < setAclAccess >FullControl</ setAclAccess > < AdditionalProviderSettings >setAclAccess</ AdditionalProviderSettings > </ MsDeploySourceManifest > |
注:由于 setAclResourceType 的默认值就是 Directory,所以可省略掉。
本质上说,MsDeploySourceManifest 是一种自定义的指令物件,依赖于 MSBuild 的可扩展性发挥作用。
而这种指令物件必须放置在<ItemGroup/>指令中,然后为了能在合适的时机执行这些指令,还需要把它们放进一个命名的<Target/>指令中,结果大概就是这样:
1 2 3 4 5 6 7 8 9 | < Target Name="MySetAcl"> < ItemGroup > < MsDeploySourceManifest Include="setAcl"> < Path >$(_MSDeployDirPath_FullPath)</ Path > < setAclAccess >FullControl</ setAclAccess > < AdditionalProviderSettings >setAclAccess</ AdditionalProviderSettings > </ MsDeploySourceManifest > </ ItemGroup > </ Target > |
而指定了名称之后,还需要在适当的生成任务中调用它,才能真正地发挥作用。
如果搜索关于 Web Deploy 和 setAcl 的文章的话,可能会发现有些文章建议在 AfterAddContentPathToSourceManifest 事件中调用这个自定义生成任务,但是实际上这样做的结果是自定义的 setAcl 指令会添加到 Web Deploy 自动生成的 setAcl 指令之前,导致我们设置的 ACL 被覆盖而失去作用。
对于这个问题,国外有同样研究自动设置 ACL 的人,给出的建议是:把调用添加在 AfterAddIisSettingAndFileContentsToSourceManifest 事件中,也就是这样:
1 2 3 | < AfterAddIisSettingAndFileContentsToSourceManifest > MySetAcl; </ AfterAddIisSettingAndFileContentsToSourceManifest > |
到现在为止,我们的 *.wpp.targets 看起来差不多就是这样了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <? xml version="1.0" encoding="utf-8" ?> < Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> < PropertyGroup > < AfterAddIisSettingAndFileContentsToSourceManifest > MySetAcl; </ AfterAddIisSettingAndFileContentsToSourceManifest > </ PropertyGroup > < Target Name="MySetAcl"> < ItemGroup > < MsDeploySourceManifest Include="setAcl"> < Path >$(_MSDeployDirPath_FullPath)</ Path > < setAclAccess >FullControl</ setAclAccess > < AdditionalProviderSettings >setAclAccess</ AdditionalProviderSettings > </ MsDeploySourceManifest > </ ItemGroup > </ Target > </ Project > |
而到这个程度,就已经可以达到“向应用程序池赋予对应用程序目录的完全控制权限”的目的了。
在进行发布之前请注意保存 *.wpp.targets,并重新加载项目。
补充说明
有两个技术细节在这里补充一下:
- 如果把 IncludeSetAclProviderOnDestination 设置为 False 的话,是可以在 AfterAddContentPathToSourceManifest 事件调用我们的自定义任务的,但是这样做到话 Web Deploy 也不会自动为匿名访问者赋予读取权限,需要我们手动添加相关的指令,所以不推荐这样做。
- 在起草本文的过程中参考了 http://leethams.com/blog/?p=102,但是本文省略掉了 AfterAddIisSettingAndFileContentsToSourceManifest 事件的条件属性,原因是:从 *.wpp.targets 导入的指令的执行顺序比较靠前,这个时候绝大部分和 Web Deploy 有关的 MSBuild 属性(包括事件)的内容都为空,条件判断的结果一定为真,没有实际意义。
另外由于实际写出来之后文章内容比预期得要长,所以为了让大家阅读起来方便一些,关于“自定义子目录的 ACL”的部分就要放到后面的部分中了,敬请期待。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· What?废柴, 还在本地部署DeepSeek吗?Are you kidding?
· 程序员转型AI:行业分析
· 为DeepSeek添加本地知识库
· 深入集成:使用 DeepSeek SDK for .NET 实现自然语言处理功能
· .NET程序员AI开发基座:Microsoft.Extensions.AI