从 ASP.NET 访问“用户实例”数据库时出现用户权限错误

Posted

技术标签:

【中文标题】从 ASP.NET 访问“用户实例”数据库时出现用户权限错误【英文标题】:User permission error when accessing "user instance" database from ASP.NET 【发布时间】:2010-11-11 04:09:38 【问题描述】:

托管 csharpindepth.com 的服务器最近已迁移。

大部分工作正常,但我无法访问用于保存勘误表、注释等的数据库。

相关详情:

32 位 Windows Server 2003 已安装 SQL Server Express 2005 在“NETWORK SERVICE”帐户下运行的 ASP.NET 池 .NET 3.5 每个人都拥有数据库文件的完全权限(目前,只是为了排除这种情况!)

连接字符串:

Data Source=.;AttachDbFilename=|DataDirectory|\WebSiteData.mdf;
Integrated Security=True;User Instance=True

我只是通过创建一个新的WebSiteDataContext 进行连接(默认使用上述连接字符串)

使用从包含文件的目录运行的小型测试控制台应用程序,作为管理员帐户,使用相同的查询,我可以看到数据库的内容。

在 ASP.NET 中,我遇到了这个异常:

SqlException (0x80131904): User does not have permission to perform this action.

编辑:更多信息,这里是堆栈跟踪:

[SqlException (0x80131904): User does not have permission to perform this action.]
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +4844759
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +194
   System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +2392
   System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK) +35
   System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnection owningObject) +144
   System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(String host, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, Int64 timerStart) +342
   System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance) +221
   System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance) +189
   System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection) +4859187
   System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options) +31
   System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject) +433
   System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject) +66
   System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) +499
   System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) +65
   System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) +117
   System.Data.SqlClient.SqlConnection.Open() +122
   System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user) +44
   System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe() +45
   System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode() +20
   System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) +57
   System.Data.Linq.DataQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +35

编辑:我错了文件名必须正确 - 更改连接字符串以使其与不同的文件通信不会更改错误。

ProcMon 从不显示它接触文件...

编辑:更奇怪的是 - 重新启动应用程序池并在本地系统帐户下运行 仍然 有问题,这和它得到的一样奇怪!就好像,尽管有错误消息,但它实际上是在尝试做一些不可能的事情(例如使用错误的路径),而不仅仅是权限问题。

编辑:更多信息 - 我刚刚从服务作为“网络服务”运行我的小测试控制台应用程序,并且(在首次尝试超时后)它成功了。因此,就用户帐户而言,这不是权限问题...它与运行环境有关...

【问题讨论】:

天哪,Jon Skeet 问了一个问题? 我认为这里几乎每个人都知道您的网站,乔恩,但我看到问题被作为垃圾邮件关闭,因为提问者通过提及和链接它来“推广”他们的网站而没有任何必要... 澄清一下:我并不想指责你任何事情。我只是想避免双重标准的印象。 好的,将编辑删除链接。 有 4422 个答案,我认为他应该得到一个无意的小插曲。 【参考方案1】:

我要做的第一件事是关闭 filemon(或者更好的是 Process Monitor) 以查看 IIS 进程是否能够打开数据库文件 - 这对我来说似乎是一个安全问题。

另外:确保 ~/App_Data 文件夹不是只读的。此外,请检查您是否已授予同一文件夹的“网络服务”帐户的完全权限。

您可能需要运行 IISRESET 来重新启动 IIS 并刷新其权限。

【讨论】:

【参考方案2】:

你做过吗?

为 Windows 配置 SQL Server 综合安全

从 Windows 开始菜单中,选择 Microsoft SQL Server,然后选择 企业经理。

打开服务器的节点,然后 为您的数据库展开节点 想给用户权限。

右键单击用户节点并选择 新数据库用户。

在“数据库用户属性”对话框中 框中,输入域\用户名在 登录名框,然后单击确定。 此外,配置 SQL Server 允许所有域用户访问 数据库。

Source

所以基本上要确认您在此处列出了“NT AUTHORITY\NETWORK SERVICE”。

至少在 SQL 2008 中也是如此,不确定 2005 是否也可以在服务器级别设置它(服务器 -> 安全 -> 登录)。

【讨论】:

服务器级别也设置了,不好玩。 也许尝试重新启动 SQL 服务并在更改后尝试重新启动 w3svc 服务。 可能也想验证新添加的登录名的权限。 是的,重新启动了各种东西。我只是希望我能找出寻找失败的过程......这似乎不是任何常见的嫌疑人。【参考方案3】:

集成安全=True

数据库中的用户登录是否连接到机器中的用户帐户?会不会有一些映射问题?

【讨论】:

数据库中没有用户登录 - 它只是一个数据库文件。【参考方案4】:

当您说用户对文件具有完全权限时,是否所有用户都对 app_data 目录具有完全权限? Sql 将需要在 MDF 文件旁边创建一个锁定文件。

您还确定 SQL Express 实例启用了用户实例吗?

【讨论】:

@blowdart:目录,是的。启用的用户实例可能是它 - 那在哪里? 我的犯罪伙伴说他检查过用户实例确实已启用。 好的,尝试暂时删除用户实例参数,看看会发生什么。以防万一它变得非常混乱。反正他们会在 2010 年离开 :) 我想应该可以。这就是我在下面给出的链接所说的内容。 是的,这以一种非常明确的方式改变了事情:“System.Data.SqlClient.SqlException:在 SQL Server 中生成用户实例被禁用。使用 sp_configure 'user instances enabled' 来生成用户实例。” 【参考方案5】:

如果您使用用户实例化,无论如何您都以管理员身份连接,这就是为什么不建议将它用于托管场景的原因。我倾向于遇到的烫发问题是文件本身的物理问题,而不是文件夹 - 分离数据库倾向于剥离烫发。

如果您可以准确缩小异常发生的位置,这可能会有所帮助。它试图执行什么操作?数据库打开,读取,写入?还尝试另一个数据库(即,它是那个特定的数据库)并尝试非用户实例版本;将数据库附加到实例。

【讨论】:

我想您已经检查过您的 SQL Server 是否支持用户实例化?见msdn.microsoft.com/en-us/library/ms254504(VS.80).aspx。 SQLEXPRESS 默认支持此功能,但您没有连接到 SQLEXPRESS,因此它可能未启用。【参考方案6】:

您是否尝试过在服务器上运行 aspnet_regsql.exe 以将某些东西恢复原状(有点像在蓝月亮中必须运行一次 aspnet_regiis)? Scott Gu 对整个过程有一个基本的概述,发现here。

【讨论】:

我不认为它是同一种工具,但还是试了一下。不过,它看起来并不适合与用户实例一起使用。 无赖。我也是这么想的,直到我看到文章的结尾并注意到配置设置与 AttachDbFilename 一起使用并认为它可能会有所帮助。【参考方案7】:

子实例甚至启动了吗?当请求 RANU 数据库时,主实例(在这种情况下为 .\SQLEXPRESS)必须创建一个“子”实例,换句话说,将 sqlservr.exe 进程作为在请求 RANU 的用户的凭据下运行的用户进程启动来自 .SQLEXPRESS 实例的连接。在这种情况下,实例必须作为“网络服务”启动。

要验证子实例是否已启动,请连接到主实例 (.\SQLEXPRESS) 并检查 sys.dm_os_child_instances:

SELECT * 
FROM sys.dm_os_child_instances

如果启动了 NETWORK SERVICE 拥有的子实例,则使用 instance_pipe_name 并直接连接到子实例:

sqlcmd -S np:\\.\pipe\<child pipe name>\tsql\query

理想情况下,作为 NETWORK SERVICE 连接(例如,从作为 NEWTORK SERVICE 启动的交互式 cmd 控制台,可能使用 at.exe 将其安排在未来 1 分钟)。如果可行,最后一步是尝试使用普通 sp_attach_db 附加 MDF。

这些步骤的想法不是解决问题,而是查明故障原因,因为您得到的错误有点笼统,而且……并不完全有帮助。

【讨论】:

没有迹象表明子实例已启动...确实我怀疑这是问题所在,但我看不出它到底在哪里失败。将我的应用程序池更改为作为本地系统运行也无济于事,这很奇怪。 启动控制台作为网络服务的最简单方法是什么?以同样的方式尝试我的测试应用会很有趣...... 我知道如何使用 AT.exe 将其作为系统启动:在晚上 10:45 /INTERACTIVE cmd (晚上 10:45 就像未来 1 分钟)。对于网络服务,我不知所措,因为我不知道如何找回它的...密码。 RUNAS 需要的是(除了我不确定 NETWORK SERVICE 是否允许在 runas 中运行)并尝试使用 sc.exe 创建一个虚拟服务: sc create cmd_as_ns binpath= c:\WINDOWS\system32\cmd.exe start= demand obj = "NETWORK SERVICE" 也需要它的密码(即使在 srvany.exe 中包装了 cmd.exe 之后)。 C:\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Microsoft SQL Server Data\SQLEXPRESS 中的任何限制可能会阻止 master/model/tempdb 的复制? 将 CMD.EXE 作为本地系统运行:blogs.msdn.com/adioltean/articles/271063.aspx【参考方案8】:

这个问题似乎与:"Cannot open user default database. Login failed." after installing SQL Server Management Studio Express

显然用户实例和 SQL Server Express 有一些有趣的问题。您可能想看看http://blogs.msdn.com/b/sqlexpress/archive/2006/11/22/connecting-to-sql-express-user-instances-in-management-studio.aspx。对于大多数有这个问题的人来说,这似乎可以解决问题。

【讨论】:

谢谢 - 如果我再次遇到它会这样做。幸运的是,我完全不再使用数据库来解决这个特定问题。只是一个 XML 文件也可以,而且要简单得多:)【参考方案9】:

由于您的 Trusted Authentication=True,连接使用调用进程的安全上下文。这意味着您正在登录用户的安全上下文中运行开发服务器,因此一切正常。在 IIS 中运行时,您处于应用程序池进程的安全上下文中,即 NETWORK SERVICE,它没有用户配置文件,因此会崩溃。

要修复,请使用解决方案 #1 或 #2。

1.) 将应用程序池的身份更改为可以访问数据库的普通用户,作为自定义帐户。提示:设置此用户:SELECT owning_principal_name FROM sys.dm_os_child_instances WHERE heart_beat = 'alive'

2.) 使用带有用户名和密码的连接字符串;意思是使用 SQL Server 身份验证,而不是 Trusted Authentication=True。

【讨论】:

以上是关于从 ASP.NET 访问“用户实例”数据库时出现用户权限错误的主要内容,如果未能解决你的问题,请参考以下文章

IIS Express 在调试 ASP.NET MVC 时出现拒绝访问错误

从 Angular 向 Asp.net 发送 post 请求时出现错误 405

IIS服务器 ASP.NET程序通过浏览器访问时出现 1310 错误

从 asp.net 核心应用程序发出 DELETE 请求时出现 405 错误

尝试实现登录时出现 ArgumentException(ASP.NET Core 项目)

从 javascript 调用 webmethod 时出现 ASP.NET 500 内部服务器错误