CS0016: 未能写入输出文件

Windows 2003、2008 中配置 ASP.NET
虚拟主机的方式一文中说明了
IIS 6 下用 ASP.NET 访问文件时需要的权限。

ASP.NET
默认情况下并不是用网站的匿名帐户来运行的,而是用一个固定的帐户来运行的,比如
Windows 2000 中是
ASPNET,显然虚拟主机中大家都用同一个帐户来运行就会造成具有相同的 NTFS
权限,这是很明显的安全隐患。在 Windows 2000
中可以通过模拟来实现不同的虚拟主机使用不同的帐户运行
ASP.NET,具体有些复杂,请参见 正确配置虚拟主机中 ASP.NET
权限。而 Windows
2003(IIS 6)配置又有不同,Windows 2008(IIS 7)中配置又不同。不过
Windows 2008 中是最方便的。

访问网页时遇到错误:

该文只说了访问是否成功,没有说具体的错误,其实透过具体的错误,我们可以进一步了解权限。

关于模拟的更多细节,请参见 ASP.NET
模拟帐户。

CS0016: 未能写入输出文件
c:WINDOWSMicrosoft.NET澳门新葡萄京官网首页 ,Frameworkv2.0.50727Temporary ASP.NET
Filesrooteb753a69572b0469App_Web_default.aspx.c7c2cb9d.4w

  • 在读 demo 文件时,失败时提示的是:未能找到文件“C:demo.txt”。
  • 在读 NS 文件时,失败时提示的是:对路径“C:ns.text”的访问被拒绝。

我们还是从模拟开始,模拟就是在 ASP.NET 配置文件中配置 <identity
impersonate=”true” />,这样运行 ASP.NET 时就不全是固定的帐户了(Windows 2000 中为
ASPNET、Windows 2003、2008 中为 Network
Service),而是运行网站的匿名帐户。为了叙述方便,我们称为半模拟(官方无此名称,仅仅是为了本文叙述方便)。

解决办法:

这可以看出,去读文件时,先是由 Network Service
去寻找,然后:如果没启用模拟的话就由 Network Service
去读;如果启用了模拟的话就由 demo 去读。所以读 NS
文件时,提示的是访问被拒绝,而不是说找不到,因为 Network Service
已经成功找到了,只是交给 demo 去读的时候 demo 无权限。而读 demo
文件时,Network Service 因无权限找不到,所以就提示未能找到文件。

模拟也可以指定特定的帐户 <identity impersonate=”true” userName=””
password=”” />,同样为了叙述方便,我们把这种称为全模拟(官方无此名称,仅仅是为了本文叙述方便)。

设置 C:Windowstemp 目录访问权限 右键 -> 属性 -> 安全 ->
添加 Network Service -> 并赋予其权限为 读 和 写 -> 确定。

我们经过测试,得出几个表,现列出来,为了便于表格不撑大,用了缩写,现将缩写说明如下:

很奇怪吧,明明是说
c:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET
Files 目录,怎么是为 C:Windowstemp
目录写权限呢,但它确实就是这个问题。

  • AppPool 应用程序池帐户
  • NS 对站点 Network Service
    是否需要对站点根目录有 NTFS 权限。
  • Principal
    System.Security.Principal.WindowsIdentity.GetCurrent().Name 的值
  • NS Network Service
  • demo 运行网站的匿名帐户
  • NS 文件 Network Service 具有读取权限的文件
  • demo 文件 deom 具有读取权限的文件
  • NSdemo 文件 Network Service、demo
    均具有读取权限的文件
  • SSPI 普通应用程序用 Windows 身份验证连接
    SQL Server 时的帐户。
  • Membership ASP.NET 中的 Membership 用
    Windows 身份验证连接 SQL Server 时的帐户。

关于以上使用 Network Service 可能受不同系统、不同配置的影响,默认
Windows Server 2003 下是用这个虚拟的用户。

另外启用全模拟时:在 Windows 2003 中,将 demo 加入了 IIS_WPG 组;在
Windows 2008 中,将 demo 加入了 IIS_IUSRS 组。不然会无法访问
C:WINDOWSMicrosoft.NETFramework 这个文件夹(实际上 2008
中加不加都可以,因为没加的话,运行时会自动动态加入)。

Windows 2003 中的情况

模拟情况 AppPool NS 对站点 Principle 读 NS 文件 读 demo 文件 读 NSdemo 文件 SSPI Membership
不启用 NS 需要 NS 成功 失败 成功 NS NS
不启用 demo 需要 NS 成功 失败 成功 NS NS
半模拟 NS 需要 demo 失败 失败 成功 demo NS
半模拟 demo 需要 demo 失败 失败 成功 demo NS
全模拟 NS 需要 demo 失败 失败 成功 demo demo
全模拟 demo 需要 demo 失败 失败 成功 demo demo

可以看出若使用半模拟,有个问题就是 Membership 用 Windows 身份验证去连接
SQL Server 时并不是运行当前网站的帐户,而是统一的 Network
Service,这点是个遗憾。使用全模拟可以解决这个遗憾,但帐户方面配置起来又很复杂。

Windows 2008 中的情况

模拟情况 AppPool NS 对站点 Principle 读 NS 文件 读 demo 文件 读 NSdemo 文件 SSPI Memberhip
不启用 NS 需要 NS 成功 失败 成功 NS NS
不启用 demo 不需要 demo 失败 成功 成功 demo demo
半模拟 NS 需要 demo 失败 成功 成功 demo NS
半模拟 demo 不需要 demo 失败 成功 成功 demo demo
全模拟 NS 需要 demo 失败 成功 成功 demo demo
全模拟 demo 不需要 demo 失败 成功 成功 demo demo

从表中可以看出,在 Windows 2008 中配置 ASP.NET
虚拟主机权限隔离非常方便,甚至都不需要什么模拟,只需要将应用程序池的帐户设置为网站的匿名帐户就可以了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注