如何实现ASP.NET身份验证:在数据库'master'中拒绝CREATE DATABASE权限。

14

首先,我已经在这里检查过了:ASP.Net Identity如何设置目标数据库?

现在我遇到了这个错误。

CREATE DATABASE权限在数据库'master'中被拒绝。

出错的代码行如下:

Dim user As User = manager.Find(Trim(Username.Text), Trim(Password.Text))

完整错误:

[SqlException (0x80131904): CREATE DATABASE permission denied in database 'master'. System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) +3249852 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +345 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +4927 System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite) +1287 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) +367 System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +386 System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch(TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed) +965 System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext) +505 System.Data.Entity.SqlServer.<>c__DisplayClass1a.b__19(DbConnection conn) +136 System.Data.Entity.SqlServer.SqlProviderServices.UsingConnection(DbConnection sqlConnection, Action`1 act) +347 System.Data.Entity.SqlServer.SqlProviderServices.UsingMasterConnection(DbConnection sqlConnection, Action`1 act) +916 System.Data.Entity.SqlServer.SqlProviderServices.CreateDatabaseFromScript(Nullable`1 commandTimeout, DbConnection sqlConnection, String createDatabaseScript) +117 System.Data.Entity.SqlServer.SqlProviderServices.DbCreateDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection) +212 System.Data.Entity.Migrations.Utilities.DatabaseCreator.Create(DbConnection connection) +172 System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) +175 System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) +116 System.Data.Entity.Internal.DatabaseCreator.CreateDatabase(InternalContext internalContext, Func`3 createMigrator, ObjectContext objectContext) +121 System.Data.Entity.Database.Create(DatabaseExistenceState existenceState) +169 System.Data.Entity.CreateDatabaseIfNotExists`1.InitializeDatabase(TContext context) +257 System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action) +72 System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() +483 System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input) +177 System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action) +274 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) +37 System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +76 System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +21 System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable.get_Provider() +59 System.Data.Entity.QueryableExtensions.FirstOrDefaultAsync(IQueryable`1 source, Expression`1 predicate, CancellationToken cancellationToken) +208 System.Data.Entity.QueryableExtensions.FirstOrDefaultAsync(IQueryable`1 source, Expression`1 predicate) +172 Microsoft.AspNet.Identity.EntityFramework.d__6c.MoveNext() +502 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13855856 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61 Microsoft.AspNet.Identity.CultureAwaiter`1.GetResult() +48 Microsoft.AspNet.Identity.d__12.MoveNext() +357 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13855856 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61 Microsoft.AspNet.Identity.AsyncHelper.RunSync(Func`1 func) +348 MyApp.Login_identity.UserLogin_Click(Object sender, EventArgs e) in C:\MyApp\Login_identity.aspx.vb:168 System.Web.UI.WebControls.Button.OnClick(EventArgs e) +11747645 System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +150 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3360]我将AppModel.vb中的DbContext初始化更改为现有的连接字符串conn1,该连接字符串指向我已经转换为新标识表的SQL Server数据库。

我的连接字符串:

<add name="conn1" 
     connectionString="data source=(local)\sqlexpress;Initial Catalog=myapp;User Id=sa;Password=XXXX;" 
     providerName="System.Data.SqlClient" />

AppModel.vb:

Imports Microsoft.AspNet.Identity
Imports Microsoft.AspNet.Identity.EntityFramework
Imports System.Collections.Generic
Imports System.ComponentModel.DataAnnotations
Imports System.Data.Entity
Imports System.Linq
Imports System.Web

Namespace AspnetIdentitySample.Models
    Public Class ApplicationUser
        Inherits IdentityUser
        ' HomeTown will be stored in the same table as Users
        Public Property HomeTown() As String
            Get
                Return m_HomeTown
            End Get
            Set(value As String)
                m_HomeTown = Value
            End Set
        End Property
        Private m_HomeTown As String
        Public Overridable Property ToDoes() As ICollection(Of ToDo)
            Get
                Return m_ToDoes
            End Get
            Set(value As ICollection(Of ToDo))
                m_ToDoes = Value
            End Set
        End Property
        Private m_ToDoes As ICollection(Of ToDo) 

        ' FirstName & LastName will be stored in a different table called MyUserInfo
        Public Overridable Property MyUserInfo() As MyUserInfo
            Get
                Return m_MyUserInfo
            End Get
            Set(value As MyUserInfo)
                m_MyUserInfo = Value
            End Set
        End Property
        Private m_MyUserInfo As MyUserInfo 
    End Class

    Public Class MyUserInfo
        Public Property Id() As Integer
            Get
                Return m_Id
            End Get
            Set(value As Integer)
                m_Id = Value
            End Set
        End Property
        Private m_Id As Integer
        Public Property FirstName() As String
            Get
                Return m_FirstName
            End Get
            Set(value As String)
                m_FirstName = Value
            End Set
        End Property
        Private m_FirstName As String
        Public Property LastName() As String
            Get
                Return m_LastName
            End Get
            Set(value As String)
                m_LastName = Value
            End Set
        End Property
        Private m_LastName As String
    End Class

    Public Class ToDo
        Public Property Id() As Integer
            Get
                Return m_Id
            End Get
            Set(value As Integer)
                m_Id = Value
            End Set
        End Property
        Private m_Id As Integer
        Public Property Description() As String
            Get
                Return m_Description
            End Get
            Set(value As String)
                m_Description = Value
            End Set
        End Property
        Private m_Description As String
        Public Property IsDone() As Boolean
            Get
                Return m_IsDone
            End Get
            Set(value As Boolean)
                m_IsDone = Value
            End Set
        End Property
        Private m_IsDone As Boolean
        Public Overridable Property User() As ApplicationUser
            Get
                Return m_User
            End Get
            Set(value As ApplicationUser)
                m_User = Value
            End Set
        End Property
        Private m_User As ApplicationUser 
    End Class
    Public Class MyDbContext
        Inherits IdentityDbContext(Of ApplicationUser)
        Public Sub New()
            MyBase.New("conn1") 'DefaultConnection
        End Sub

        Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
            MyBase.OnModelCreating(modelBuilder)

            ' Change the name of the table to be Users instead of AspNetUsers
            modelBuilder.Entity(Of IdentityUser)().ToTable("Users")
            modelBuilder.Entity(Of ApplicationUser)().ToTable("Users")
        End Sub

        Public Property ToDoes() As DbSet(Of ToDo)
            Get
                Return m_ToDoes
            End Get
            Set(value As DbSet(Of ToDo))
                m_ToDoes = Value
            End Set
        End Property
        Private m_ToDoes As DbSet(Of ToDo)

        Public Property MyUserInfo() As DbSet(Of MyUserInfo)
            Get
                Return m_MyUserInfo
            End Get
            Set(value As DbSet(Of MyUserInfo))
                m_MyUserInfo = Value
            End Set
        End Property
        Private m_MyUserInfo As DbSet(Of MyUserInfo)
    End Class


End Namespace

更新

根据一条评论,我也在这里进行了检查。

我真的不明白为什么这是一个角色问题,因为我正在重用一个连接字符串,该连接字符串已经可以正常更新其他(与标识相关的非)表。此外,我不明白为什么错误涉及到master表,因为我希望我没有通过manager.Find方法以任何方式尝试连接到它。

无论如何,我当前测试的用户已经被分配到sysadmin角色:

enter image description here

更新2

好的,感谢Jeremy在下面的评论,我又近了一步...我需要将用户IIS APPPOOL\.NET v4.5添加到sysadmin角色中,因为这是SQL Server Profiler中显示的连接用户(虽然我不确定添加此用户到此角色时的安全风险)。无论如何,Find方法不再抛出错误,并且当我执行此代码Dim user As User = manager.FindByName(Trim(Username.Text))时,使用SQL Server Profiler可以看到SQL语句已经被触发。

exec sp_executesql N'SELECT TOP (1) 
[Extent1].[Id] AS [Id], 
[Extent1].[ApplicationId] AS [ApplicationId], 
[Extent1].[MobileAlias] AS [MobileAlias], 
[Extent1].[IsAnonymous] AS [IsAnonymous], 
[Extent1].[LastActivityDate] AS [LastActivityDate], 
[Extent1].[MobilePIN] AS [MobilePIN], 
[Extent1].[LoweredEmail] AS [LoweredEmail], 
[Extent1].[LoweredUserName] AS [LoweredUserName], 
[Extent1].[PasswordQuestion] AS [PasswordQuestion], 
[Extent1].[PasswordAnswer] AS [PasswordAnswer], 
[Extent1].[IsApproved] AS [IsApproved], 
[Extent1].[IsLockedOut] AS [IsLockedOut], 
[Extent1].[CreateDate] AS [CreateDate], 
[Extent1].[LastLoginDate] AS [LastLoginDate], 
[Extent1].[LastPasswordChangedDate] AS [LastPasswordChangedDate], 
[Extent1].[LastLockoutDate] AS [LastLockoutDate], 
[Extent1].[FailedPasswordAttemptCount] AS [FailedPasswordAttemptCount], 
[Extent1].[FailedPasswordAttemptWindowStart] AS [FailedPasswordAttemptWindowStart], 
[Extent1].[FailedPasswordAnswerAttemptCount] AS [FailedPasswordAnswerAttemptCount], 
[Extent1].[FailedPasswordAnswerAttemptWindowStart] AS [FailedPasswordAnswerAttemptWindowStart], 
[Extent1].[Comment] AS [Comment], 
[Extent1].[Email] AS [Email], 
[Extent1].[EmailConfirmed] AS [EmailConfirmed], 
[Extent1].[PasswordHash] AS [PasswordHash], 
[Extent1].[SecurityStamp] AS [SecurityStamp], 
[Extent1].[PhoneNumber] AS [PhoneNumber], 
[Extent1].[PhoneNumberConfirmed] AS [PhoneNumberConfirmed], 
[Extent1].[TwoFactorEnabled] AS [TwoFactorEnabled], 
[Extent1].[LockoutEndDateUtc] AS [LockoutEndDateUtc], 
[Extent1].[LockoutEnabled] AS [LockoutEnabled], 
[Extent1].[AccessFailedCount] AS [AccessFailedCount], 
[Extent1].[UserName] AS [UserName]
FROM [dbo].[AspNetUsers] AS [Extent1]
WHERE ((UPPER([Extent1].[UserName])) = (UPPER(@p__linq__0))) OR ((UPPER([Extent1].[UserName]) IS NULL) AND (UPPER(@p__linq__0) IS NULL))',N'@p__linq__0 nvarchar(4000)',@p__linq__0=N'flo@outlook.com'

奇怪的是:当我在SQL Server Management Studio中直接执行它时,会返回一条记录,但在我的代码中,变量userNothing。那是什么原因呢?


这确实不是我所期望的。数据库myapp已经存在。就好像我在这里传递的自定义数据库连接字符串被忽略了一样:Public Sub New() MyBase.New("conn1") 'DefaultConnection End Sub - Adam
错误指的是主数据库,而不是主表。 - StingyJack
主数据库包含整个服务器范围的信息,包括系统中的所有数据库。这就是为什么在创建数据库时它会“参与”其中的原因。请参考:https://msdn.microsoft.com/zh-cn/library/ms187837.aspx - larsts
这明显是一个权限问题。当Entity Framework连接到服务器时,它无法“看到”myapp数据库。我建议在服务器上创建一个新的登录账户,并授予sysadmin权限,然后在你的连接字符串中使用该账户。 - larsts
它正在尝试创建一个新的数据库,因为您的上下文设置是这样的,它会重新创建数据库,而不是通过迁移更新它。 但正如其他人所说,这确实是一个权限问题。 - Zoran P.
显示剩余6条评论
5个回答

4

如果您的应用程序池是在NETWORK SERVICE身份下运行,请尝试这样做。然后为“NT AUTHORITY\NETWORK SERVICE”授予SysAdmin角色:

enter image description here

或者将SysAdmin授权给运行应用程序池的任何帐户。

如果这样做不起作用,请检查以下解决方案是否有所帮助:CREATE DATABASE permission denied in database 'master' (EF code-first)

编辑:

将所有这些帐户设为SysAdmin并不安全。在解决此问题后,将SQL安全性加强到仅限于dbReader和dbWriter角色。

FindByName方法出了什么问题?

现在没有异常了,但是问题是没有返回任何数据,我认为仍然存在权限问题。

由于您在连接字符串中使用了SQL身份验证,您可以尝试使用Windows集成身份验证吗?否则,请尝试在连接字符串中使用appPool IIS帐户凭据,并查看是否能够找出问题所在?


我已将sysadmin角色添加到“NT AUTHORITY\NETWORK SERVICE”。但是这并没有帮助...我在哪里可以看到运行应用程序池的帐户?顺便说一下,你提到的帖子并没有解决我的问题 :( - Adam
1
是时候启动我们的SQL Server Profiler并进行跟踪了!看看里面发生了什么?谁在执行操作?你知道,它是否正在被冒名顶替?让我们找出来! - Jeremy Thompson
谢谢!我又进了一步,我已经更新了我的帖子(请参见更新2)。你能看一下吗?添加这个角色是安全的吗?FindByName方法出了什么问题? - Adam
你的更新在哪里?我没有看到任何新评论或更新的答案? - Adam
好的,我会尽快测试这个。无论如何,我现在会奖励你赏金,否则它会过期,而你的答案最接近解决这个问题:)希望你能帮我完全解决这个问题。谢谢! - Adam

1
您的连接字符串中包含 "User Id=sa;Password=XXXX",因此该连接尝试使用 SQL Server 身份验证。您的 SSMS 登录属性标题栏似乎标识了一个 Windows 帐户,这意味着存在一种信念认为应该使用 Windows 身份验证。然而,该连接尝试使用 SQL Server 身份验证(而不是 Windows 身份验证)。如果还没有配置,可以更改 SQL Server 的身份验证模式以支持 SQL 身份验证和 Windows 身份验证("混合模式" 身份验证),请参见 https://msdn.microsoft.com/zh-cn/library/ms188670.aspx
或者,可以更改连接字符串以使用 Windows 身份验证/集成安全性,请参见 https://msdn.microsoft.com/zh-cn/library/jj653752(v=vs.110).aspx#integratedsecurity

不是这个问题...我已经启用了该服务器的Windows和SQL Server身份验证。用户sa已经拥有所有权限。还可能是什么问题? - Adam
用SELECT USER替换CREATE DATABASE语句。 如果返回'dbo',则您的登录是sysadmin角色的成员。 如果返回除'dbo'之外的某个名称(包括'sa'),则您的帐户不是sysadmin角色的成员。如果返回'sa',则可能已重命名sa帐户并创建了一个新帐户命名为'sa'(新的'sa'帐户不是syadmin角色的成员)。sysadmin还可以拒绝自己或其他sysadmin帐户的权限(因为拒绝访问优先于所有权限),但sysadmin(也称为DBO用户)可以删除该拒绝。 - Bill
好的,抱歉耽搁了一下,但我一直在尝试解决这个问题...我在哪里可以替换那个语句?我猜它被编译代码包裹在manager.Find方法后面。请给予建议... - Adam
我认为你不能在设置中替换那个语句。但是,你可以使用连接字符串中的信息在SSMS中进行手动连接,以检查你的sa账户是否正常。也就是说,使用你的sa账户,在管理工具中使用SQL身份验证进行连接。 - larsts

0

为什么不使用哈希值在NVARCHAR()字段中,而不是使用标识字段?

例如:您可以从用户获取单个数据(或其字段的连接),使用.NET加密库计算哈希值,并将该NVARCHAR()设置为数据。

这样(假设您正在使用SHA-512哈希),您将能够拥有一个Base64字符串的单个数据,就像身份本身一样。

但是,如果您的目标是拥有“动量”的身份,则可以获取用户数据以及当前日期时间,计算其哈希并将此数据保存为记录的身份。


我真的想利用Identity框架提供的方法,而不是采用变通方法。但是,“have an identity to the momentum”这句话我不太明白……它是什么意思? - Adam
请记住,在数据库清理/压缩例程中,Identity 可能会发生变化。您是指在 ASP.NET Identity 框架中通常如此吗?如果是这样:那么这意味着什么呢? - Adam
我不确定我们是否在谈论同一件事,但这份报告可能会对您有所帮助:http://sqlmag.com/t-sql/should-i-use-identity-or-not。如果我没有完全满足您的需求,请见谅。 - David BS
啊,我们说的不是同一件事情,我在谈论的是ASP.NET Identity,这是aspnet成员表的新版本。无论如何,还是谢谢你。 - Adam
哇,很抱歉让你浪费时间了。最好的祝福。 - David BS
显示剩余2条评论

0

你最好使用一个不同于“sa”的SQL账户,但是“sa”的默认数据库为master。即使在连接字符串中定义了myapp,Find方法很可能仍然使用用户的默认数据库。

将“sa”的默认数据库更改为myapp,如下:

enter image description here


嗨,谢谢你,但是用户sa的默认数据库已经设置为myapp了... 仍然出现相同的错误。 - Adam

-1

您的用户应该添加到dbcreator角色中。

否则,您将无法创建新数据库。

Sysadmin/public不足以满足需求。


2
系统管理员没有创建数据库的权限? - StingyJack
不,它没有。 每次我忘记添加它时,我都会遇到这个问题。 :D - Ismail Hassani
@IsmailHassani 谢谢,但是当我尝试将角色“dbcreator”添加到我的用户“sa”时,我收到错误消息“无法使用特殊主体'sa'”,我发现他的帖子提到它已经是sysadmin组的成员,这比所有其他组都更重要:http://stackoverflow.com/questions/14188629/cannot-use-the-special-principal-sa 那我该怎么办?(我尝试在作为用户“sa”登录以及通过Windows身份验证添加角色到此用户) - Adam
2
系统管理员是访问权限的最高角色,可以在服务器上执行任何活动。https://msdn.microsoft.com/en-us/library/ms188659(v=sql.105).aspx。开箱即用的“sa”用户已经隐式地拥有dbcreator权限,因此您的设置可能存在其他问题。SQL或Windows事件日志中是否有任何消息? - StingyJack
系统管理员角色足以创建新的数据库,这个答案是错误的。 - larsts
显示剩余3条评论

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