有没有办法让IIS可以在不使用NT SERVICE\NETWORK SERVICE
用户帐户的情况下连接到LocalDB。
此帐户没有合适的权限。我正在寻找使用其他一些默认帐户,或者是否有某些方法可以在不更改权限的情况下使用NETWORK SERVICE
帐户?
答案 0 :(得分:13)
您应该使用LocalDB的共享实例功能。使用LocalDB和完整IIS的这两篇帖子应该会为您提供更多信息。特别是第二部分看似相关,但第一部分也包含一些背景。
(注意:原始链接不再可用,而是使用archive.org)
原件(截至2019年3月未工作)链接:
答案 1 :(得分:0)
我们面临的问题是需要加载用户配置文件。这应该不难,因为每个 IIS 应用程序池都有一个名为加载用户配置文件的选项,可以在高级设置部分找到。不幸的是,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 应用程序。
我这边的注意事项: 只需在该 applicationHost 文件中找到“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'.
这次的错误很明显了。 LocalDB 已启动并且 Web 应用程序能够连接到它,但由于登录失败,连接随后被终止。 IIS 应用程序池的 ApplicationPoolIdentity 帐户(在本例中为 IIS APPPOOL\ASP.NET v4.0)无法登录到 LocalDB 实例,因为连接字符串中指定的数据库 (OldFashionedDB< /strong>) 未找到。多么奇怪,因为使用相同的连接字符串从 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 中作为 ApplicationPoolIdentity 运行的 Web 应用程序连接到 LocalDB 时,会为其启动另一个 LocalDB 实例并作为 ApplicationPoolIdentity 运行!实际上,即使 Visual Studio 和 Web 应用程序使用相同的 LocalDB 连接字符串,它们也连接到不同的 LocalDB 实例。显然,在我们的 LocalDB 实例上从 Visual Studio 创建的数据库在 Web 应用程序的 LocalDB 实例中将不可用。
Windows 中的 My Documents 文件夹就是一个很好的类比。假设我们打开 Visual Studio 并在我们的 我的文档 文件夹中创建一个文件。然后我们以不同的用户身份登录到同一台计算机并再次转到 我的文档 文件夹。我们不会在那里找到该文件,因为第二个用户的我的文档和我们的 我的文档 是两个不同的文件夹。类似地,两个不同用户拥有的 LocalDB 实例 (localdb)\v11.0 是具有两个不同数据库集的两个不同进程。
这也是 Web 应用程序能够从 IIS Express 连接到 LocalDB 的原因。就像 LocalDB 一样,IIS Express 是一个用户进程。它由 Visual Studio 启动并作为与 Visual Studio 进程相同的 Windows 帐户运行。连接到 (localdb)\v11.0 的两个以同一个 Windows 帐户运行的不同进程(Visual Studio 和 IIS Express,都以我们的 Windows 帐户运行)正在连接到同一个 LocalDB 进程,也以相同的 Windows 帐户。
了解问题的本质可以带来多种解决方法。由于不同的方法有不同的权衡,下面我没有规定一种解决方案,而是介绍了三种对我来说似乎最可行的方法。我希望听到你的声音,告诉你最适合你的那个!名单如下:
Approach 1: Run IIS as our Windows user
Approach 2: Use LocalDB Shared Instance
Approach 3: Use full SQL Server Express
让我们仔细看看它们中的每一个。
如果不同的用户帐户是问题,为什么不尝试在我们的 Windows 帐户下运行我们的 Web 应用程序? Web 应用程序将连接到与 Visual Studio 相同的 LocalDB,一切正常。
进行配置更改相对容易,只需启动 IIS 管理器并找到合适的应用程序池:
打开高级设置屏幕(在上下文菜单中可用):
点击身份属性中的小按钮以显示应用程序池身份屏幕:
再次启动 Web 应用程序将确认问题已解决:
这种方法的缺点是什么?当然,在我们的账户下运行 Web Application 会带来一定的安全风险。如果有人劫持了我们的 Web 应用程序,他们将能够访问我们帐户可以访问的所有系统资源。将 Web 应用程序作为 ApplicationPoolIdentity 运行可提供额外的保护,因为 ApplicationPoolIdentity 帐户对本地系统资源的访问非常有限。因此,我一般不推荐这种方法,但如果谨慎使用,它在某些情况下是一个可行的选择。
我们还可以使用 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 对象资源管理器连接到它即可启动它并使其保持活动状态。进入 SQL Server 对象资源管理器后,我们还可以为 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 Data Tools 来完成它,因为它适用于任何 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 CTP 和 Beta 遗留的组件等问题阻止。 SQL Server Express 即使在不需要时也会继续在后台运行,就像服务一样。
在完整的 IIS 下还有其他使用 LocalDB 的方法,这里没有介绍。我们可以包含 Web 应用程序的私有 LocalDB 实例,并通过从 ASP.NET 代码执行 T-SQL 脚本通过 Web 应用程序与它通信。我们还可以使用 ADO.NET 连接字符串的 AttachDbFileName 选项,并使用一个数据库文件 (.mdf),该文件将在开发期间附加到我们的 LocalDB 和 Web 应用程序的 LocalDB 以进行调试。我都试过了,但发现它们太麻烦了,无法进一步讨论。
答案 2 :(得分:0)
基于@KrzysztofKozielczyk 的回答。
我最初在这里发布了一个答案:
https://stackoverflow.com/a/62810876/3850405
按照此操作后,我确认 Load User Profile
为我的 Application Pool
设置为 true,然后在 setProfileEnvironment
中将 true
设置为 applicationHost.config
。我通过编辑位于以下位置的 applicationHost.config
完成了最后一部分:
C:\Windows\System32\inetsrv\config\applicationHost.config