ASP.NET Identity 2.0 Roles.IsUserInRole 给出 "Invalid object name 'dbo.aspnet_SchemaVersions'.&qu

Posted

技术标签:

【中文标题】ASP.NET Identity 2.0 Roles.IsUserInRole 给出 "Invalid object name \'dbo.aspnet_SchemaVersions\'." 异常【英文标题】:ASP.NET Identity 2.0 Roles.IsUserInRole gives "Invalid object name 'dbo.aspnet_SchemaVersions'." exceptionASP.NET Identity 2.0 Roles.IsUserInRole 给出 "Invalid object name 'dbo.aspnet_SchemaVersions'." 异常 【发布时间】:2014-12-24 22:22:11 【问题描述】:

我使用 ASP.NET Identity 2.0,我想知道登录的用户是否具有“管理员”角色。在我的种子方法中,我创建了 3 个不同的角色,如下所示:

var store = new UserStore<ApplicationUser>(context);
               var userManager = new ApplicationUserManager(store);
               var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

               string roleName = "admin";
               if (!roleManager.RoleExists(roleName))
               
                   roleManager.Create(new IdentityRole(roleName));
               
               roleName = "superuser";
               if (!roleManager.RoleExists(roleName))
               
                   roleManager.Create(new IdentityRole(roleName));
               
               roleName = "user";
               if (!roleManager.RoleExists(roleName))
               
                   roleManager.Create(new IdentityRole(roleName));
               


               var user = new ApplicationUser()  Email = "nsg@gmail.com", UserName = "Niclas" ;
               userManager.Create(user, "123456");
               userManager.AddToRole(user.Id, "Admin");

取决于用户是否是管理员,他需要在导航栏中看到不同的链接,所以我做了这个代码:

        <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @html.ActionLink("Lenio", "Index", "Home", new  area = "" , new  @class = "navbar-brand" )
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    @if (Roles.IsUserInRole(User.Identity.Name,"admin"))
                    
                        <li>@Html.ActionLink("Admins", "Index", "Admins")</li>
                        <li>@Html.ActionLink("SuperUsers", "Index", "SuperUsers")</li>
                        <li>@Html.ActionLink("Users", "Index", "Users")</li>
                        <li>@Html.ActionLink("Areas", "Index", "Areas")</li>
                        <li>@Html.ActionLink("CDs", "Index", "CommunicationDevices")</li>
                        <li>@Html.ActionLink("Houses", "Index", "Houses")</li>
                        <li>@Html.ActionLink("Lendings", "Index", "Lendings")</li>
                        <li>@Html.ActionLink("Logs", "Index", "Logs")</li>
                        <li>@Html.ActionLink("Sensors", "Index", "Sensors")</li>
                    
                    @if (User.IsInRole("user"))
                    
                        <li>@Html.ActionLink("User", "Index", "Din bruger")</li>
                    
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>

问题是当代码到达@if (Roles.IsUserInRole(User.Identity.Name,"admin")) 部分时,我得到一个"Invalid object name 'dbo.aspnet_SchemaVersions'." 异常。我的数据库中没有 aspnet_SchemaVersions 表,我不想要它。 这是与我拥有的身份相关的表格的图片:

数据库托管在 azure 上。

更新

DavidG 发布了一个解决初始问题的答案,但它没有解决我无法使用的问题:

[Authorize(Roles = "admin")]

我需要能够使用这个属性,但我不能,因为我得到了这个异常:

> [SqlException (0x80131904): Invalid object name 'dbo.aspnet_SchemaVersions'.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +1789294
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5340642
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +244
   System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +1691
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +275
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds) +1421
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) +177
   System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) +208
   System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +163
   System.Web.Util.SecUtility.CheckSchemaVersion(ProviderBase provider, SqlConnection connection, String[] features, String version, Int32& schemaVersionCheck) +392
   System.Web.Security.SqlRoleProvider.CheckSchemaVersion(SqlConnection connection) +64
   System.Web.Security.SqlRoleProvider.GetRolesForUser(String username) +753
   System.Web.Security.RolePrincipal.IsInRole(String role) +9625099
   System.Linq.Enumerable.Any(IEnumerable`1 source, Func`2 predicate) +146
   System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext) +333
   System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) +379
   System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor) +143
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__19(AsyncCallback asyncCallback, Object asyncState) +1680
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +59
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151
   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) +94
   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +559
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +82
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +73
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151
   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +105
   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +588
   System.Web.Mvc.Controller.<BeginExecute>b__14(AsyncCallback asyncCallback, Object callbackState, Controller controller) +47
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +65
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151
   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +139
   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +484
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +98
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +73
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +151
   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback callback, Object callbackState, BeginInvokeDelegate`1 beginDelegate, EndInvokeVoidDelegate`1 endDelegate, TState invokeState, Object tag, Int32 timeout, SynchronizationContext callbackSyncContext) +106
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +446
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +88
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +50
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

【问题讨论】:

【参考方案1】:

出现此错误的原因是您的应用程序尝试首先使用旧版本的 Identity 进行连接。您不应使用对象的“旧”版本来管理角色。使用新的 UserManagerRoleManager 类。

例如:

var store = new UserStore<ApplicationUser>(context);
var userManager = new ApplicationUserManager(store);    

if(userManager.IsInRole(userId, "NameOfRole")

    //do stuff

要在您的视图中使用它,您可以创建自己的助手:

namespace MyProject.MyNamespace.MyExtensions

    public static class IdentityExtensions
    
        public static bool IsInIdentityRole(this IPrincipal user, string role)
        
            var userManager = GetUserManager(); //implement this!
            return userManager.IsInRole(user.Identity.GetUserId(), role); 
        
    

确保您的视图知道此命名空间,将此行添加到您的 Views 文件夹中的 web.config 文件中(不是主要的 web.config!):

<add namespace="MyProject.MyNamespace.MyExtensions"/>

并像这样在您的视图中使用:

@if (User.IsInIdentityRole("admin"))

    <li>@Html.ActionLink("Admins", "Index", "Admins")</li>

【讨论】:

我在其中使用它的视图是 _Layout.cshtml 我应该将辅助方法放在哪里才能在该视图中访问它们? GetUserManager() 除了return new ApplicationUserManager(store) 还应该做什么? 更新了答案以包含它。 我实现的 GetManager() 方法与您的第一个示例一样,并且您所说的其他方法都有效。 -1 很抱歉,您不需要在创建UserManager 对象的地方创建带有静态扩展的hack。 IPrinciple 实现了 IsInRole() 方法,并且与 Identity 配合得非常好。在 Razor 视图中,您会得到 IPrincipal 类型的 User,如果您调用 @User.IsInRole("admin") - 它会告诉您用户是否处于管理员角色。无需去数据库。 @Niclassg 在您的web.config 中,在&lt;system.web&gt; 中确保此行存在:&lt;roleManager enabled="false" /&gt;【参考方案2】:

而不是调用

@if (Roles.IsUserInRole(User.Identity.Name,"admin"))

对旧 MembershipProvider 的调用使用此调用:

@if (User.IsInRole("admin"))

这使用了新身份框架的功能。无需实现任何东西。这也不会调用数据库来检查角色 - 它使用存储用户角色的 cookie 信息。

更新

如果您收到关于 System.Web.Security.RolePrincipal 的异常,这意味着您的会员服务提供商并未完全关闭,您看到它正在与最后的机会作斗争。

确保在您的web.config 中有:

<system.WebServer>
     <modules>
       <remove name="FormsAuthentication" />

<appSettings>
    <add key="enableSimpleMembership" value="false" />

确保您的 cookie 已被删除,并且您可以再次登录。之后,当您在调试器的 Razor 视图中检查 @User 时,您应该看到 ClaimsPrincipal 对象,而不是 RolePrincipal。当用户登录时,ClaimsPrincipal 应该在整个系统中使用——这就是 Identity 使用的。如果您没有收到IdentityPrincipal,则表示您的登录过程无法正常工作。

【讨论】:

当我尝试使用@if (User.IsInRole("admin")) 时出现System.Data.SqlClient.SqlException' occurred in System.Web.dll but was not handled in user code 错误,详细信息为:Invalid object name 'dbo.aspnet_SchemaVersions'. 用户类型为:User = System.Web.Security.RolePrincipal 我确保我在 web.config 文件中有这些设置,并删除了所有 cookie,但它没有帮助。 您的登录代码是什么样的?这个错误是 MembershipProvider 遗留下来的,所以它在某个地方仍然存在,会打乱你的进程。 我通过将 &lt;roleManager enabled="false" 添加到 web.config 来修复它 您的web.config 中似乎还有关于 MembershipProvider 的部分。您需要杀死所有启用 &lt;MembershipProvider&gt;&lt;ProfileProvider&gt; 等的东西。

以上是关于ASP.NET Identity 2.0 Roles.IsUserInRole 给出 "Invalid object name 'dbo.aspnet_SchemaVersions'.&qu的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Identity 2.0 中获取当前用户 ID

如何在现有数据库中实现 ASP.NET Identity 2.0?

Asp.net Identity 2.0 更新用户

ASP.NET Identity 2.0 解密 Owin cookie

迁移到 Asp.Net Identity 2.0:未在 AspNetUsers 表中创建新列

Asp.NET Core 2.0 API 控制器中的 User.Identity.Name 为空