IIS是否可以在不使用NT SERVICE\NETWORK SERVICE
用户帐户的情况下连接到LocalDB?
该帐户没有适当的权限。我想使用其他默认帐户,或者有没有一些方法可以在不更改权限的情况下使用NETWORK SERVICE
账户?
我们面临的问题是需要加载用户配置文件。这不应该很难,因为每个IIS应用程序池都有一个名为Load User Profile的选项,可以在高级设置部分找到。不幸的是,在Windows 7 Service Pack 1中,事情变得稍微复杂了一些。如KB 2547655所述,启用loadUserProfile并不足以完全加载用户配置文件,我们还需要启用setProfileEnvironment。这需要编辑applicationHost.config文件,该文件通常位于C:\Windows\System32\inetsrv\config中。按照KB 2547655的说明,我们应该为应用程序池ASP.NET v4.0同时启用两个标志,如下所示:
<add name="ASP.NET v4.0" autoStart="true" managedRuntimeVersion="v4.0" managedPipelineMode="Integrated">
<processModel identityType="ApplicationPoolIdentity" loadUserProfile="true" setProfileEnvironment="true" />
</add>
完成这些步骤后,我们重新启动应用程序池以确保新的设置已应用,并再次运行Web应用程序。
我的注意事项:只需在应用程序主机文件中找到“applicationPools”标签,并将这两个变量更新为true,使其看起来像这样:
<processModel identityType="ApplicationPoolIdentity" loadUserProfile="true" setProfileEnvironment="true" />
完成后,保存文件并重新启动IIS池。
正如我们所看到的,我们面临以下错误:
System.Data.SqlClient.SqlException: Cannot open database "OldFashionedDB" requested by the login. The login failed.
Login failed for user 'IIS APPPOOL\ASP.NET v4.0'.
Data Source=(localdb)\v11.0;Initial Catalog=OldFashionedDB;Integrated Security=True
这个问题可以用Windows的我的文档文件夹来做类比。假设我们打开Visual Studio并在我们的我的文档文件夹中创建一个文件。然后我们登录为不同的用户,再次进入我的文档文件夹。我们将不会在那里找到该文件,因为第二个用户的我的文档和我们的我的文档是两个不同的文件夹。类似地,由两个不同用户拥有的LocalDB实例(localdb)\v11.0是两个不同的进程,具有两个不同的数据库集。
这也是Web应用程序能够从IIS Express连接到LocalDB的原因。就像LocalDB一样,IIS Express是一个用户进程。它由Visual Studio启动,并以与Visual Studio进程相同的Windows帐户身份运行。作为以相同Windows帐户身份运行的两个不同进程(Visual Studio和IIS Express,均以我们的Windows帐户身份运行),连接到(localdb)\v11.0的是连接到相同的LocalDB进程,该进程也是以相同的Windows帐户身份启动的。
理解问题的本质可以采用多种方法来解决它。由于不同的方法有不同的权衡,因此我提出了三种最可行的方法,而不是规定一种解决方案。希望能听到您哪种方法最适合您!以下是列表:
方法1:以我们的Windows用户身份运行IIS
方法2:使用共享的LocalDB实例
方法3:使用完整版SQL Server Express
让我们更详细地了解每种方法。
如果不同的用户帐户是问题所在,为什么不尝试在我们的Windows帐户下运行Web应用程序?Web应用程序将连接到与Visual Studio相同的LocalDB,一切都应该正常工作。
进行配置更改相对容易,只需启动IIS管理器,找到正确的应用程序池:
打开高级设置窗口(在上下文菜单中可用):
点击身份验证属性中的小按钮,以打开应用程序池标识窗口:
重新启动Web应用程序可确认该问题已解决:
这种方法的缺点是什么?当然,在我们的帐户下运行Web应用程序会带来某些安全风险。如果有人劫持了我们的Web应用程序,他们将能够访问我们的帐户所能访问的所有系统资源。以ApplicationPoolIdentity身份运行Web应用程序会提供额外的保护,因为ApplicationPoolIdentity帐户对本地系统资源的访问非常有限。因此,我不能通常推荐使用这种方法,但在某些情况下,谨慎使用是一种可行的选择。
我们还可以使用LocalDB的实例共享功能。它允许我们与同一台机器上的其他用户共享一个LocalDB实例。共享的实例将在公共名称下可访问。
共享实例的最简单方法是使用SqlLocalDB.exe工具。只需启动管理员命令行提示符,并键入以下命令:
sqllocaldb share v11.0 IIS_DB
Data Source=(localdb)\.\IIS_DB;Initial Catalog=OldFashionedDB;Integrated Security=True
在 Web 应用程序使用共享实例之前,我们需要启动它并为 ApplicationPoolIdentity 创建登录。启动实例很容易,只需从 SQL Server Object Explorer 连接到它即可启动它并保持运行状态。一旦进入 SQL Server Object Explorer,我们也可以创建 ApplicationPoolIdentity 的登录。我们可以使用以下查询:
create login [IIS APPPOOL\ASP.NET v4.0] from windows;
exec sp_addsrvrolemember N'IIS APPPOOL\ASP.NET v4.0', sysadmin
此脚本为ApplicationPoolIdentity账户提供对LocalDB实例的完全管理访问权限。如果可能的话,建议使用更有限制性的基于数据库甚至表级别的权限。
现在我们可以再次运行Web应用程序。这次它应该能够正常工作:
这种方法的缺点是什么? 主要问题在于,在Web应用程序可以连接到共享实例之前,我们需要确保实例已启动。为了实现这一点,拥有该实例的Windows帐户必须连接到它,并且连接必须保持开放状态,否则LocalDB实例将关闭。
由于完整版IIS作为服务运行,也许使用传统的、基于服务的SQL Server Express是正确的方法?我们只需安装SQL Server 2012 Express RC0并在其中创建OldFashionedDB数据库即可。我们甚至可以使用全新的SQL Server数据工具来完成它。因为它适用于任何SQL Server版本和版本系列。我们的连接字符串将需要更改为:
Data Source=.\SQLEXPRESS;Initial Catalog=OldFashionedDB;Integrated Security=True
create login [IIS APPPOOL\ASP.NET v4.0] from windows;
exec sp_addsrvrolemember N'IIS APPPOOL\ASP.NET v4.0', sysadmin
接着,运行我们的Web应用程序后,又看到了愉快的画面:
显然,我们失去了使用LocalDB的好处。安装SQL Server Express可能需要比LocalDB更长的时间,并且可能需要一些机器清理才能成功。 SQL Server Express的安装可能会受到各种问题的阻挠,例如损坏的WMI数据库、污染的注册表或由SQL Server或Visual Studio CTPs和Betas留下的组件。而且,即使不需要,SQL Server Express也会像服务一样继续在后台运行。
还有其他方法可以在完整的IIS下使用LocalDB,这里没有涵盖。我们可以使用Web应用程序的私有LocalDB实例,并通过执行ASP.NET代码中的T-SQL脚本与之通信。我们也可以使用ADO.NET连接字符串的AttachDbFileName选项,并使用一个数据库文件(.mdf)来同时附加到我们的LocalDB(开发时)和Web应用程序的LocalDB(调试时)。我尝试过这两种方法,但发现它们过于繁琐,无法进一步讨论。
根据@KrzysztofKozielczyk的答案。
我最初在这里发布了一个答案:
https://stackoverflow.com/a/62810876/3850405
按照这个方法,我验证了我的应用程序池中的Load User Profile
被设置为true,然后在applicationHost.config
中将setProfileEnvironment
设置为true
。我通过编辑位于以下位置的applicationHost.config
来完成最后一步:
C:\Windows\System32\inetsrv\config\applicationHost.config