IIS 连接本地数据库(LocalDB)

16

IIS是否可以在不使用NT SERVICE\NETWORK SERVICE用户帐户的情况下连接到LocalDB?

该帐户没有适当的权限。我想使用其他默认帐户,或者有没有一些方法可以在不更改权限的情况下使用NETWORK SERVICE账户?

4个回答

21

那么通过这个答案,我可以在IIS中使用LocalDB,对吗? - saulyasar
我会用它进行开发,但是对于生产环境,我会选择常规的基于服务的SQL Server,例如常规的SQL Express实例。第二篇博客文章会更详细地介绍。 - Krzysztof Kozielczyk
实际上我的问题是,让我解释一下。我正在创建一个使用个人账户的WebAPI 2项目,该项目使用从Visual Studio自动创建的本地数据库,并且我正在使用此数据库来创建令牌和存储用户信息,但是当我将此项目发布到IIS时,我无法访问该本地数据库?我该如何访问它? - saulyasar
1
链接似乎已经失效了! - Jurgen Cuschieri
@JurgenCuschieri 确实,看起来我们旧的 SQL Express 博客在三月份某个时候被删除了。感谢您的提醒!我会尝试使用 archive.org 上的链接。 - Krzysztof Kozielczyk

4

如果链接再次消失,我将从文章中复制解决方案以便更易于访问:

帖子1:

我们面临的问题是需要加载用户配置文件。这不应该很难,因为每个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池。

帖子2:

私有实例的问题

正如我们所看到的,我们面临以下错误:

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'.

这次错误非常明显。 LocalDB已经启动,Web应用程序能够连接到它,但由于登录失败,连接随后被终止。 IIS应用程序池的ApplicationPoolIdentity帐户(在本例中为 IIS APPPOOL \ ASP.NET v4.0 )无法登录到LocalDB实例,因为在连接字符串中指定的数据库( OldFashionedDB )未找到。多么奇怪,因为使用相同的连接字符串从Visual Studio连接会成功! 为什么Visual Studio可以正常连接到LocalDB,而Web应用程序的连接失败呢? 在两种情况下,连接字符串都是以下内容:
Data Source=(localdb)\v11.0;Initial Catalog=OldFashionedDB;Integrated Security=True

答案是这里有两个不同的LocalDB实例。与运行为Windows服务的SQL Server Express实例不同,LocalDB实例作为用户进程运行。当不同的Windows用户连接到LocalDB时,将会为每个用户启动不同的LocalDB进程。当我们从Visual Studio连接到(localdb)\v11.0时,会为我们启动一个LocalDB实例,并以我们的Windows帐户身份运行。但是,当运行在IIS中的Web应用程序以ApplicationPoolIdentity身份连接到LocalDB时,将为其启动另一个LocalDB实例,并以ApplicationPoolIdentity身份运行!实际上,即使Visual Studio和Web应用程序都使用相同的LocalDB连接字符串,它们也连接到不同的LocalDB实例。显然,在我们的LocalDB实例上从Visual Studio创建的数据库将不会在Web应用程序的LocalDB实例中可用。

这个问题可以用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

让我们更详细地了解每种方法。

方法1:以我们的Windows用户身份运行IIS

如果不同的用户帐户是问题所在,为什么不尝试在我们的Windows帐户下运行Web应用程序?Web应用程序将连接到与Visual Studio相同的LocalDB,一切都应该正常工作。

进行配置更改相对容易,只需启动IIS管理器,找到正确的应用程序池:

打开高级设置窗口(在上下文菜单中可用):

点击身份验证属性中的小按钮,以打开应用程序池标识窗口:

重新启动Web应用程序可确认该问题已解决:

这种方法的缺点是什么?当然,在我们的帐户下运行Web应用程序会带来某些安全风险。如果有人劫持了我们的Web应用程序,他们将能够访问我们的帐户所能访问的所有系统资源。以ApplicationPoolIdentity身份运行Web应用程序会提供额外的保护,因为ApplicationPoolIdentity帐户对本地系统资源的访问非常有限。因此,我不能通常推荐使用这种方法,但在某些情况下,谨慎使用是一种可行的选择。

方法2:使用共享的LocalDB实例

我们还可以使用LocalDB的实例共享功能。它允许我们与同一台机器上的其他用户共享一个LocalDB实例。共享的实例将在公共名称下可访问。

共享实例的最简单方法是使用SqlLocalDB.exe工具。只需启动管理员命令行提示符,并键入以下命令:

sqllocaldb share v11.0 IIS_DB

它将在公共名称IIS_DB下共享私有LocalDB实例v11.0。机器上的所有用户都将能够使用(localdb)。\IIS_DB作为服务器地址连接到此实例。请注意,实例名称前面的点表示这是一个共享实例名称。我们应该使用更新后的连接字符串替换Web应用程序中的连接字符串。
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实例将关闭。

方法3:使用完整版SQL Server Express

由于完整版IIS作为服务运行,也许使用传统的、基于服务的SQL Server Express是正确的方法?我们只需安装SQL Server 2012 Express RC0并在其中创建OldFashionedDB数据库即可。我们甚至可以使用全新的SQL Server数据工具来完成它。因为它适用于任何SQL Server版本和版本系列。我们的连接字符串将需要更改为:

Data Source=.\SQLEXPRESS;Initial Catalog=OldFashionedDB;Integrated Security=True

当然,就像之前一样,我们需要确保ApplicationPoolIdentity帐户可以访问我们的SQL Server Express实例。我们可以使用与之前相同的脚本:
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(调试时)。我尝试过这两种方法,但发现它们过于繁琐,无法进一步讨论。


1

根据@KrzysztofKozielczyk的答案。

我最初在这里发布了一个答案:

https://stackoverflow.com/a/62810876/3850405

按照这个方法,我验证了我的应用程序池中的Load User Profile被设置为true,然后在applicationHost.config中将setProfileEnvironment设置为true。我通过编辑位于以下位置的applicationHost.config来完成最后一步:

C:\Windows\System32\inetsrv\config\applicationHost.config

enter image description here


0
由于某种原因,在我的情况下,无法从IIS 10 网站访问(localdb)\mssqllocaldb实例。
尝试了许多设置,但没有任何效果。
最后,在IIS的网站的Application Pool的高级设置中,将'Load User Profile = True'设置为解决了我的问题。
我的应用程序池标识是一个Windows用户账户

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