将SimpleMembership数据库迁移到Identity 2后,User.IsInRole失败 [英] User.IsInRole failing after migrating SimpleMembership database to Identity 2

查看:451
本文介绍了将SimpleMembership数据库迁移到Identity 2后,User.IsInRole失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将我的应用程序从MVC4-EF5更新到MVC5-EF6。



然后,我将数据库从Simplemebership迁移到Identity 2.0。



我可以登录,但User.IsInRole总是返回false。所有正确的表AspNetUsers,AspNetRoles,AspNetUserRoles,AspNetLogins和AspNetClaims都已创建,所有列的拼写和类型都是正确的,并且已经从SimpleMembership表(已被删除)中的数据填充。



我在AspNetUsers表中有一个Id = 2的用户MyUser,AspNetRoles表和User 2中的Id = 2的角色XYZ在AspNetUserRoles表中映射到角色2。



以MyUser身份登录



var user = _db.Users.SingleOrDefault(u => u.UserName == User.Identity.Name);

用户确实设置为MyUser但是



User.IsInRole(XYZ)返回false。



我添加了一个测试变量
var testrole = Roles.GetRolesForUser(); 在调试中检查它返回一个空字符串数组{string [0]}。从立即窗口运行 User.IsInRole(XYZ)返回false。



文档我可以找到Identity,Identity 2.0和从SimpleMembership和Identity 1.0迁移,我找不到任何实现要求(超出了我在我的贴子代码中做了什么),我错过了使身份工作(并且它正在工作



我已经使用Identity 2.0的可扩展性钩子来实现我的主键的INT。



WebSecConfig.cs :(从Global.asax.cs调用)(删除此代码为更新:1)

 使用WebMatrix.WebData; 

命名空间MyApplication
{
public static class WebSecConfig
{
public static void RegisterWebSec()
{
WebSecurity.InitializeDatabaseConnection
(MyApplication,AspNetUsers,Id,UserName,autoCreateTables:true);
}
}
}

ApplicationUser:

  public class ApplicationUser:IdentityUser< int,CustomUserLogin,CustomUserRole,CustomUserClaim> 
{
[StringLength(15)]
public new string UserName {get;组; }
public int AcId {get;组; }
public int LcId {get;组; }
}

public class CustomRole:IdentityRole< int,CustomUserRole>
{
public CustomRole(){}
public CustomRole(string name){Name = name; }
}

public class CustomUserRole:IdentityUserRole< int> {}
public class CustomUserClaim:IdentityUserClaim< int> {}
public class CustomUserLogin:IdentityUserLogin< int> {}

IdentityDbContext:

  public class MyDb:IdentityDbContext< ApplicationUser,CustomRole,int,CustomUserLogin,CustomUserRole,CustomUserClaim> 
{
public MyDb():base(MyApplication){}

// public virtual DbSet< UserProfiles>用户{get;组; }
public virtual DbSet&MyTable> MyTables {get;组; } //属性标记为虚拟的Mocking覆盖
...

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove< PluralizingTableNameConvention>();
}

帐户控制器:

  [RequireHttps] 
[授权]
public class AccountController:Controller
{
private readonly IUserService _userService;

public UserManager< ApplicationUser,int> UserManager {get;私人集合}

public AccountController()
:this(new UserService(),new UserManager< ApplicationUser,int>(new UserStore< ApplicationUser,CustomRole,int,CustomUserLogin,CustomUserRole,CustomUserClaim> new MyDb ()))){}

public AccountController(IUserService userService,UserManager< ApplicationUser,int> userManager)
{_userService = userService; UserManager = userManager;

// GET:/ Account / Login
[AllowAnonymous]
public ActionResult Login(){return View();

// POST:/ Account / Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult登录(LoginVm vM)
{
if(ModelState.IsValid)
{
var user = UserManager.Find(vM.UserName,vM.Password);
if(user!= null)
{
FormsAuthentication.SetAuthCookie(user.UserName,false);
return RedirectToAction(UserRouting,Home);
}
}
ModelState.AddModelError(,提供的用户名或密码不正确);

return View(vM);
}

家庭控制器:

 使用系统; 
使用System.Web.Mvc;
使用MyApplication.Models;
使用System.Linq;
使用System.Web.Security;

命名空间MyApplication.Controllers
{
[授权]
public class HomeController:Controller
{
private readonly MyDb _db = new MyDb );

public ActionResult UserRouting()
{
var user = _db.Users.SingleOrDefault(u => u.UserName == User.Identity.Name);
var testrole = Roles.GetRolesForUser(); //用于测试,从生产中删除
if(User.IsInRole(XYZ)){// mycode}
...
}
}

迁移脚本:(以 SimpleMembershipToIdentityMigration.sql ,并为Identity 2.0和INT主键修改)

  / ******对象:表[dbo]。[AspNetRoles]脚本日期:4/30/14 ****** / 
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

如果OBJECT_ID('dbo.AspNetUserRoles','U')IS NOT NULL
DROP TABLE [dbo]。 [AspNetUserRoles]
GO
--IF OBJECT_ID('dbo.AspNetUserLogins','U')IS NOT NULL
- DROP TABLE [dbo]。[AspNetUserLogins]
- -GO
如果OBJECT_ID('dbo.AspNetUserClaims','U')IS NOT NULL
DROP TABLE [dbo]。[AspNetUserClaims]
G O
如果OBJECT_ID('dbo.AspNetRoles','U')IS NOT NULL
DROP TABLE [dbo]。[AspNetRoles]
GO
IF OBJECT_ID('dbo.AspNetUsers ','U')IS NOT NULL
DROP TABLE [dbo]。[AspNetUsers]
GO

CREATE TABLE [dbo]。[AspNetUsers](
- - [Id] NVARCHAR(128)NOT NULL,
[Id] INT NOT NULL,
[UserName] NVARCHAR(15)NULL,
[AcId] INT NOT NULL,
[LcId] INT NOT NULL,
[电子邮件] NVARCHAR(256)NULL,
[EmailConfirmed] BIT DEFAULT((0))NULL,
[PasswordHash] NVARCHAR(MAX)NULL,
[SecurityStamp] NVARCHAR(MAX)NULL,
[PhoneNumber] N BARCH DEFAULT((0))NULL,
[LockoutEndDateUtc] DATETIME NULL,
[LockoutEnabled] BIT DEFAULT((0))NULL,
[AccessFailedCount] INT DEFAULT((0))NOT NULL,
[CreateDate] DATETIME NULL,
CONSTRAINT [PK_dbo.AspNetUsers ]主键集合([Id] ASC)
);
GO
CREATE TABLE [dbo]。[AspNetRoles](
- [Id] NVARCHAR(128)NOT NULL,
[Id] INT NOT NULL,
[名称] NVARCHAR(256)NOT NULL,
CONSTRAINT [PK_dbo.AspNetRoles] PRIMARY KEY CLUSTERED([Id] ASC)
);
GO
CREATE TABLE [dbo]。[AspNetUserRoles](
- [UserId] NVARCHAR(128)NOT NULL,
- [RoleId] NVARCHAR(128)NOT NULL ,
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserRoles] PRIMARY KEY CLUSTERED([UserId] ASC,[RoleId] ASC),
CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId] FOREIGN KEY([RoleId])REFERENCES [dbo]。[AspNetRoles]([Id])ON DELETE CASCADE,
CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId] FOREIGN KEY([ UserId])REFERENCES [dbo]。[AspNetUsers]([Id])ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_RoleId]
ON [dbo]。[AspNetUserRoles]([RoleId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
ON [dbo]。[AspNetUserRoles]([UserId] ASC);
GO
CREATE TABLE [dbo]。[AspNetUserLogins](
- [UserId] NVARCHAR(128)NOT NULL,
[UserId] INT NOT NULL,
[LoginProvider] NVARCHAR(128)NOT NULL,
[ProviderKey] NVARCHAR(128)NOT NULL,
CONSTRAINT [PK_dbo.AspNetUserLogins] PRIMARY KEY CLUSTERED([UserId] ASC,[LoginProvider] ASC,[ProviderKey ] ASC),
CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId] FOREIGN KEY([UserId])REFERENCES [dbo]。[AspNetUsers]([Id])ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
ON [dbo]。[AspNetUserLogins]([UserId] ASC);
GO

CREATE TABLE [dbo]。[AspNetUserClaims](
[Id] INT IDENTITY(1,1)NOT NULL,
[ClaimType] NVARCHAR )NULL,
[ClaimValue] NVARCHAR(MAX)NULL,
- [UserId] NVARCHAR(128)NOT NULL,
[UserId] INT NOT NULL,
CONSTRAINT [PK_dbo .AspNetUserClaims] PRIMARY KEY CLUSTERED([Id] ASC),
CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_User_Id] FOREIGN KEY([UserId])REFERENCES [dbo]。[AspNetUsers]([Id])ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_User_Id]
ON [dbo]。[AspNetUserClaims]([UserId] ASC);
GO

INSERT INTO AspNetUsers(Id,UserName,AcId,LcId,PasswordHash,SecurityStamp,CreateDate)
SELECT UserProfile.UserId,UserProfile.UserName,UserProfile.BaId,UserProfile。 OfcId,
webpages_Membership.Password,webpages_Membership.PasswordSalt,CreateDate
FROM UserProfile
LEFT OUTER JOIN webpages_Membership ON UserProfile.UserId = webpages_Membership.UserId
GO

INSERT INTO AspNetRoles(Id,Name)
SELECT RoleId,RoleName
FROM webpages_Roles
GO

INSERT INTO AspNetUserRoles(UserId,RoleId)
SELECT UserId, RoleId
FROM webpages_UsersInRoles
GO

IF OBJECT_ID('dbo.webpages_OAuthMembership','U')IS NOT NULL
DROP TABLE [dbo]。[webpages_OAuthMembership]
GO

如果OBJECT_ID('dbo.webpages_UsersInRoles','U')IS NOT NULL
DROP TABLE [dbo]。[webpages_UsersInRoles]
GO
IF OBJECT_ID('dbo.webpages_Roles','U')IS NOT NULL
DROP TABLE [dbo ] [webpages_Roles]
GO
如果OBJECT_ID('dbo.UserProfile','U')IS NOT NULL
DROP TABLE [dbo]。[UserProfile]
GO
IF OBJECT_ID('dbo.webpages_Membership','U')IS NOT NULL
DROP TABLE [dbo]。[webpages_Membership]
GO

IF OBJECT_ID('dbo。 __MigrationHistory','U')IS NOT NULL
DROP TABLE [dbo]。[__ MigrationHistory] ​​
GO

我错过了配置Identity 2.0的内容,还是Identity 2.0中的错误?



更新1:
删除对WebSecConfig的Global.asax.cs调用。这已经掩盖了一个不同的问题与 User.IsInRole。



在家庭控制器UserRouting操作中的var用户上设置断点

在调试中运行应用程序并以MyUser身份登录。

进入并将用户设置为MyUser。

进入var testrole抛出'对象引用未设置为对象的实例'。



重新启动并重新登录为 MyUser。

进入,用户被设置为MyUser。

从即时窗口输入 User.IsInRole(XYZ)并返回:

 系统中发生类型为System.Data.SqlClient.SqlException的第一次机会异常。 Data.dll 
System.Data.dll中发生类型为System.Data.SqlClient.SqlException的第一次机会异常
类型为System.Data.SqlClient.SqlException的第一次机会异常发生在System.Data.dll
发生类型为System.Data.SqlClient.SqlException的第一次机会异常在System.Data.dll
System.Web.dll中发生类型System.Web.HttpException的第一次机会异常
系统中发生类型System.Web.HttpException的第一次机会异常.Web.dll
System.Web.dll中发生类型为System.Web.HttpException的第一次机会异常

并打开一个警告对话框:

  HttpException未处理
未处理的异常在System.Web.dll中发生System.Web.HttpException
附加信息:无法连接到SQL Server数据库。

我的基本数据库设置是正确的,否则我将无法登录。这导致我相信我如何运行迁移有一个小的差异。有人有一个想法,我绊倒了。



更新2:
我重构代码和迁移脚本以使用默认nvarchar为主键,并获得与更新1相同的结果。



更新3:



Web.Config:

 <?xml version =1.0encoding =utf-8?> ; 
<! -
有关如何配置ASP.NET应用程序的更多信息,请访问
http://go.microsoft.com/fwlink/?LinkId=169433
- >
< configuration>
< configSections>
< section name =entityFrameworktype =System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection,EntityFramework,Version = 6.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089requirePermission =false/> ;

<! - 有关实体框架配置的更多信息,请访问http://go.microsoft.com/fwlink/?LinkID=237468 - >
< sectionGroup name =nwebsec>
<! - 有关如何配置NWebsec的信息,请访问:http://nwebsec.codeplex.com/wikipage?title=Configuration - >
< section name =httpHeaderSecurityModuletype =NWebsec.Modules.Configuration.HttpHeaderSecurityConfigurationSection,NWebsec,Version = 3.0.2.0,Culture = neutral,PublicKeyToken = 3613da5f958908a1requirePermission =false/>
< / sectionGroup>
< sectionGroup name =elmah>
< section name =securityrequirePermission =falsetype =Elmah.SecuritySectionHandler,Elmah/>
< section name =errorLogrequirePermission =falsetype =Elmah.ErrorLogSectionHandler,Elmah/>
< section name =errorMailrequirePermission =falsetype =Elmah.ErrorMailSectionHandler,Elmah/>
< section name =errorFilterrequirePermission =falsetype =Elmah.ErrorFilterSectionHandler,Elmah/>
< / sectionGroup>

<! - 有关实体框架配置的更多信息,请访问http://go.microsoft.com/fwlink/?LinkID=237468 - >< / configSections>
< connectionStrings>
< add name =MyApplicationconnectionString =data source = .\SqlExpress; Integrated Security = SSPI; MultipleActiveResultSets = true; initial catalog = MyDbproviderName =System.Data.SqlClient/>
< / connectionStrings>
< appSettings>
< add key =webpages:Versionvalue =3.0.0.0/>
< add key =webpages:Enabledvalue =false/>
< add key =PreserveLoginUrlvalue =true/>
< add key =ClientValidationEnabledvalue =true/>
< add key =UnobtrusiveJavaScriptEnabledvalue =true/>
< add key =elmah.mvc.disableHandlervalue =false/>
< add key =elmah.mvc.disableHandleErrorFiltervalue =false/>
< add key =elmah.mvc.requiresAuthenticationvalue =true/>
< add key =elmah.mvc.IgnoreDefaultRoutevalue =false/>
< add key =elmah.mvc.allowedRolesvalue =Admin,CorpS/>
<! - < add key =elmah.mvc.allowedUsersvalue =*/> - >
< add key =elmah.mvc.routevalue =elmah/>
< / appSettings>
<! -
有关web.config更改的说明,请参阅http://go.microsoft.com/fwlink/?LinkId=235367。

以下属性可以在< httpRuntime>标签。
< system.Web>
< httpRuntime targetFramework =4.5.1/>
< /system.Web>
- >
< system.web>
< customErrors mode =Off/>
< compilation debug =truetargetFramework =4.5.1/>
< httpRuntime targetFramework =4.5useFullyQualifiedRedirectUrl =truemaxRequestLength =100000enableVersionHeader =false/>
<! - 值是Kb,需要避免与大文件的文件上传崩溃 - >
< authentication mode =Forms>
< forms loginUrl =〜/ Account / Logintimeout =15/>
< / authentication>
< pages>
< namespaces>
< add namespace =System.Web.Helpers/>
< add namespace =System.Web.Mvc/>
< add namespace =System.Web.Mvc.Ajax/>
< add namespace =System.Web.Mvc.Html/>
< add namespace =System.Web.Optimization/>
< add namespace =System.Web.Routing/>
< add namespace =System.Web.WebPages/>
< / namespaces>
< / pages>
<! - < roleManager enabled =truedefaultProvider =simple>
< providers>
< clear />
< add name =simpletype =WebMatrix.WebData.SimpleRoleProvider,WebMatrix.WebData/>
< / providers>
< / roleManager>
< membership defaultProvider =simple>
< providers>
< clear />
< add name =simpletype =WebMatrix.WebData.SimpleMembershipProvider,WebMatrix.WebData/>
< / providers>
< / membership> - >
< httpModules>
< add name =ErrorLogtype =Elmah.ErrorLogModule,Elmah/>
< add name =ErrorMailtype =Elmah.ErrorMailModule,Elmah/>
< add name =ErrorFiltertype =Elmah.ErrorFilterModule,Elmah/>
< / httpModules>
< sessionState cookieName =My_SessionId/>
< /system.web>
< system.webServer>
< validation validateIntegratedModeConfiguration =false/>
<处理程序>
< remove name =ExtensionlessUrlHandler-Integrated-4.0/>
< remove name =OPTIONSVerbHandler/>
< remove name =TRACEVerbHandler/>
< add name =ExtensionlessUrlHandler-Integrated-4.0path =*。 verb =*type =System.Web.Handlers.TransferRequestHandlerpreCondition =integratedMode,runtimeVersionv4.0/>

< / handlers>
< modules>
< add name =NWebsecHttpHeaderSecurityModuletype =NWebsec.Modules.HttpHeaderSecurityModule,NWebsec,Version = 3.0.2.0,Culture = neutral,PublicKeyToken = 3613da5f958908a1/>
< add name =ErrorLogtype =Elmah.ErrorLogModule,ElmahpreCondition =managedHandler/>
< add name =ErrorMailtype =Elmah.ErrorMailModule,ElmahpreCondition =managedHandler/>
< add name =ErrorFiltertype =Elmah.ErrorFilterModule,ElmahpreCondition =managedHandler/>
< remove name =RoleManager/>
< / modules>
< httpProtocol>
< customHeaders>
< clear />
< / customHeaders>
< / httpProtocol>
< security>
< requestFiltering>
< hiddenSegments>
< add segment =NWebsecConfig/>
< / hiddenSegments>
< / requestFiltering>
< / security>
< /system.webServer>
<运行时>
< assemblyBinding xmlns =urn:schemas-microsoft-com:asm.v1>
< dependentAssembly>
< assemblyIdentity name =WebGreasepublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-1.6.5135.21930newVersion =1.6.5135.21930/>
< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =System.Net.Http.FormattingpublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-5.1.0.0newVersion =5.1.0.0/>
< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =System.Web.HttppublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-5.1.0.0newVersion =5.1.0.0/>
< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =Microsoft.Data.ODatapublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-5.6.1.0newVersion =5.6.1.0/>
< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =Microsoft.Data.EdmpublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-5.6.1.0newVersion =5.6.1.0/>
< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =System.SpatialpublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-5.6.1.0newVersion =5.6.1.0/>
< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =System.Web.RazorpublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-3.0.0.0newVersion =3.0.0.0/>
< / dependentAssembly>
< dependentAssembly>< assemblyIdentity name =System.Web.HelperspublicKeyToken =31bf3856ad364e35/>
< bindingRedirect oldVersion =1.0.0.0-3.0.0.0newVersion =3.0.0.0/>< / dependentAssembly>
< dependentAssembly>< assemblyIdentity name =System.Web.WebPagespublicKeyToken =31bf3856ad364e35/>
< bindingRedirect oldVersion =0.0.0.0-3.0.0.0newVersion =3.0.0.0/>< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =System.Web.WebPages.RazorpublicKeyToken =31bf3856ad364e35culture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-3.0.0.0newVersion =3.0.0.0/>
< / dependentAssembly>
< dependentAssembly>< assemblyIdentity name =System.Web.MvcpublicKeyToken =31bf3856ad364e35/>< bindingRedirect oldVersion =0.0.0.0-5.1.0.0newVersion =5.1.0.0/ >< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =Newtonsoft.JsonpublicKeyToken =30ad4fe6b2a6aeedculture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-6.0.0.0newVersion =6.0.0.0/>
< / dependentAssembly>
< dependentAssembly>
< assemblyIdentity name =Antlr3.RuntimepublicKeyToken =eb42632606e9261fculture =neutral/>
< bindingRedirect oldVersion =0.0.0.0-3.5.0.2newVersion =3.5.0.2/>
< / dependentAssembly>
< / assemblyBinding>
<! - 这样可以防止Windows事件日志经常记录正在使用HMAC1(当对方需要它时)。 - >
< legacyHMACWarning enabled =0/>
<! - 当定位ASP.NET MVC 3时,这个assemblyBinding使MVC 1和2引用将
重新链接到MVC 3,因此像MVC 1编译的DotNetOpenAuth这样的库将可以使用它。
< assemblyBinding xmlns =urn:schemas-microsoft-com:asm.v1>
< dependentAssembly>
< assemblyIdentity name =System.Web.MvcpublicKeyToken =31bf3856ad364e35/>
< bindingRedirect oldVersion =1.0.0.0-3.0.0.0newVersion =3.0.0.0/>
< / dependentAssembly>
< / assemblyBinding>
- >
< / runtime>
< entityFramework>
< defaultConnectionFactory type =System.Data.Entity.Infrastructure.SqlConnectionFactory,EntityFramework/>
< providers>
< provider invariantName =System.Data.SqlClienttype =System.Data.Entity.SqlServer.SqlProviderServices,EntityFramework.SqlServer/>
< / providers>
< / entityFramework>
< system.net>
< defaultProxy enabled =true/>
< settings>
<! - 此设置使.NET在信任HTTPS证书之前检查证书吊销列表(CRL)
。但这种设置往往不能在共享托管环境中允许
。 - >
<! - < servicePointManager checkCertificateRevocationList =true/> - >
< / settings>
< /system.net>
< nwebsec>
< httpHeaderSecurityModule xmlns =http://nwebsec.com/HttpHeaderSecurityModuleConfig.xsdxmlns:xsi =http://www.w3.org/2001/XMLSchema-instancexsi:noNamespaceSchemaLocation =NWebsecConfig / HttpHeaderSecurityModuleConfig.xsd>
< redirectValidation enabled =true> < add allowedDestination =https:// localhost //> < / redirectValidation>
< securityHttpHeaders>
< x-Frame-Options policy =Deny/>
< strict-Transport-Security max-age =365/>
< x-Content-Type-Options enabled =true/>
< / securityHttpHeaders>
< / httpHeaderSecurityModule>
< / nwebsec>
< elmah>
< security allowRemoteAccess =false/>
< / elmah>

< / configuration>

我需要添加< remove name =RoleManager/> 作为 MVC4-MVC5 迁移,我现在已经完成了。



现在我回到原来的问题了。 User.IsInRole总是返回false。
如果我从即时窗口运行 User.IsAuthenticated ,则返回

 'System.Security.Principal.IPrincipal'不包含'IsAuthenticated'的定义,并且没有扩展方法'IsAuthenticated'接受类型'System.Security.Principal.IPrincipal'的第一个参数可以找到(你错过了一个使用指令或程序集引用?)

我能够获取Identity.UserManager.IsInRole工作



家庭控制器:(修改为使用UserManager)

 使用系统; 
使用System.Web.Mvc;
使用Microsoft.AspNet.Identity;
使用Microsoft.AspNet.Identity.EntityFramework;
使用MyApplication.Models;
使用System.Linq;
//使用System.Web.Security;

命名空间MyApplication.Controllers
{
[授权]
public class HomeController:Controller
{
private readonly MyDb _db = new MyDb );
public UserManager< ApplicationUser> UserManager {get;私人集合}
public HomeController()
:this(new UserManager< ApplicationUser>(new UserStore< ApplicationUser>(new MyDb())){}
public HomeController(UserManager< ApplicationUser> userManager)
{UserManager = userManager; }

public ActionResult UserRouting()
{
var user = _db.Users.SingleOrDefault(u => u.UserName == User.Identity.Name);
// var testrole = Roles.GetRolesForUser(); //用于测试,从生产中删除
if(UserManager.IsInRole(user.Id,XYZ)){// mycode}
...
}
}

这表示我的数据库迁移是正确的。



我在我的应用程序的控制器,视图,自定义属性,方法和类中有几十个对User.IsInRole的调用。对于我的理解User.IsInRole在MVC5-EF6中仍然是一个有效的方法。
如果仍然被认为是一种有效的方法,而不必对此旧版应用程序进行重大重构,那么我再次提出我的原始问题为什么SimpleMembership到Identity 2.0迁移后User.IsInRole失败?



我在Identity 1.0 MVC应用程序中测试过User.IsInRole,它的工作原理。我将应用程序更新为Identity 2.0,它仍然可行。所以我觉得用Identity.IsInRole支持Identity 2.0是安全的。

解决方案

进一步调查后,我发现问题是我从未成功登录,由于用户未通过身份验证 User.IsInRole 失败。

  var user = UserManager.Find (vM.UserName,vM.Password); 

当您在调试中检查用户MyUser 已被发现,但如果您进一步向下钻取,您会发现 UserName 设置为null。

 code> User 
- {System.Data.Entity.DynamicProxies.ApplicationUser _...} Identity.Models.ApplicationUser {System.Data.Entity.DynamicProxies.ApplicationUser _...} ...
base {System.Data.Entity.DynamicProxies.ApplicationUser _...} Identity.Models.ApplicationUser {System.Data.Entity.DynamicProxies.ApplicationUser _...}
base {System.Data.Entity.DynamicProxies.ApplicationUser_。 ..} Microsoft.AspNet.Identity.EntityFramework.IdentityUser ...
base {System.Data.Entity.DynamicProxies.ApplicationUser _...} Microsoft.AspNet.Identity.EntityFramework.IdentityUser< string,Microsoft.AspNet.Identity。 ..
AccessFailedCount 0 int
声明计数= 0 System.Collections.Generi c.ICollection< Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim> ...
电子邮件null string
EmailConfirmed false bool
Id2string
LockoutEnabled false bool
LockoutEndDateUtc null System.DateTime?
登录计数= 0 System.Collections.Generic.ICollection< Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin> ...
PasswordHashxxxxxxstring
PhoneNumber空字符串
PhoneNumberConfirmed false bool
角色计数= 2 System.Collections.Generic.ICollection< Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole> ...
SecurityStampstring
TwoFactorEnabled false bool
UserName空字符串

ApplicationUser 我覆盖了UserName。

  [StringLength(15 )] 
public new string UserName {get;组; }

当我删除UserName覆盖所有开始工作(我离开UserName作为nvarchar(15)不为空)。问题在于 ApplicationUser 中的 UserName 覆盖。如果您想更改nvarchar大小,您显然只需在迁移脚本中执行此操作。



从SimpleMembrship迁移到Identity 2.0工作。 User.IsInRole也适用于Identity 2.0。


I successfully updated my application from MVC4-EF5 to MVC5-EF6.

I then migrated my database from Simplemebership to Identity 2.0.

I can login but User.IsInRole always returns false. All the proper tables AspNetUsers, AspNetRoles, AspNetUserRoles, AspNetLogins and AspNetClaims have been created, the spelling and type of all columns are correct and they have been populated with the data from the SimpleMembership tables (which have been deleted).

I have a user "MyUser" which is Id = 2 in the AspNetUsers table and a role "XYZ" which is Id = 2 in the AspNetRoles table and User 2 is mapped to Role 2 in the AspNetUserRoles table.

When logged in as "MyUser"

var user = _db.Users.SingleOrDefault(u => u.UserName == User.Identity.Name);
user does get set to "MyUser" but

User.IsInRole("XYZ") returns false.

I added a test variable, var testrole = Roles.GetRolesForUser();, when testrole is examined in debug it returns an empty string array {string[0]}. Running User.IsInRole("XYZ") from the Immediate Window returns false.

I've read through every document I can find on Identity, Identity 2.0 and migrating from SimpleMembership and Identity 1.0 and I can't find any implementation requirements (beyond what I've done in my posted code) that I have missed to make Identity work (and it is working at some level since then login works).

I have used Identity 2.0's extensibility hook to implement INT for my Primary keys.

WebSecConfig.cs: (called from Global.asax.cs) (removed this code for UPDATE: 1)

using WebMatrix.WebData;

namespace MyApplication
{ 
  public static class WebSecConfig
  {
    public static void RegisterWebSec()
    {
      WebSecurity.InitializeDatabaseConnection 
        ("MyApplication", "AspNetUsers", "Id", "UserName", autoCreateTables: true);
    }
  }
}

ApplicationUser:

  public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
  { 
    [StringLength(15)]
    public new string UserName { get; set; }
    public int AcId { get; set; }
    public int LcId { get; set; }
  }

  public class CustomRole : IdentityRole<int, CustomUserRole>
  {
    public CustomRole() { }
    public CustomRole(string name) { Name = name; }
  }

  public class CustomUserRole : IdentityUserRole<int> { }
  public class CustomUserClaim : IdentityUserClaim<int> { }
  public class CustomUserLogin : IdentityUserLogin<int> { }

IdentityDbContext:

  public class MyDb : IdentityDbContext<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>
  {
    public MyDb() : base("MyApplication") { }

    // public virtual DbSet<UserProfiles> Users { get; set; }
    public virtual DbSet<MyTable> MyTables { get; set; } // properties marked virtual for Mocking override
    ...

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
  {
    base.OnModelCreating(modelBuilder);
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
  }

Account Controller:

  [RequireHttps]
  [Authorize]
  public class AccountController : Controller
  {
    private readonly IUserService _userService;

    public UserManager<ApplicationUser, int> UserManager { get; private set; }

    public AccountController() 
    : this(new UserService(), new UserManager<ApplicationUser, int>(new UserStore<ApplicationUser, CustomRole, int, CustomUserLogin, CustomUserRole, CustomUserClaim>new MyDb()))) { } 

    public AccountController(IUserService userService, UserManager<ApplicationUser, int> userManager)
    { _userService = userService; UserManager = userManager; }

    // GET: /Account/Login
    [AllowAnonymous]
    public ActionResult Login() { return View(); }

    // POST: /Account/Login
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Login(LoginVm vM)
    { 
      if (ModelState.IsValid) 
      { 
        var user = UserManager.Find(vM.UserName, vM.Password);
        if (user != null)
        { 
          FormsAuthentication.SetAuthCookie(user.UserName, false);
          return RedirectToAction("UserRouting", "Home");
        }
      } 
      ModelState.AddModelError("", "The user name or password provided is incorrect.");

      return View(vM);
    }

Home Controller:

using System;
using System.Web.Mvc;
using MyApplication.Models;
using System.Linq;
using System.Web.Security;

namespace MyApplication.Controllers
{
  [Authorize]
  public class HomeController : Controller
  {
    private readonly MyDb _db = new MyDb(); 

    public ActionResult UserRouting()
    {
      var user = _db.Users.SingleOrDefault(u => u.UserName == User.Identity.Name);
      var testrole = Roles.GetRolesForUser();  // for testing, remove from production
      if (User.IsInRole("XYZ")) { // mycode }
      ...
     }
  }

Migration Script: (modeled on SimpleMembershipToIdentityMigration.sql and modified for Identity 2.0 and INT Primary Keys)

    /****** Object: Table [dbo].[AspNetRoles] Script Date: 4/30/14 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

IF OBJECT_ID('dbo.AspNetUserRoles', 'U') IS NOT NULL
    DROP TABLE [dbo].[AspNetUserRoles]
GO
--IF OBJECT_ID('dbo.AspNetUserLogins', 'U') IS NOT NULL
--  DROP TABLE [dbo].[AspNetUserLogins]
--GO
IF OBJECT_ID('dbo.AspNetUserClaims', 'U') IS NOT NULL
    DROP TABLE [dbo].[AspNetUserClaims]
GO
IF OBJECT_ID('dbo.AspNetRoles', 'U') IS NOT NULL
    DROP TABLE [dbo].[AspNetRoles]
GO
IF OBJECT_ID('dbo.AspNetUsers', 'U') IS NOT NULL
    DROP TABLE [dbo].[AspNetUsers]
GO

CREATE TABLE [dbo].[AspNetUsers] (
    --[Id]                                    NVARCHAR (128) NOT NULL,
    [Id]                                      INT            NOT NULL,
    [UserName]                                NVARCHAR (15)  NULL,
    [AcId]                                    INT            NOT NULL,
    [LcId]                                    INT            NOT NULL,
    [Email]                                   NVARCHAR (256) NULL,
    [EmailConfirmed]                          BIT            DEFAULT ((0)) NULL,
    [PasswordHash]                            NVARCHAR (MAX) NULL,
    [SecurityStamp]                           NVARCHAR (MAX) NULL,  
    [PhoneNumber]                             NVARCHAR (MAX) NULL,
    [PhoneNumberConfirmed]                    BIT            DEFAULT ((0)) NULL,
    [TwoFactorEnabled]                        BIT            DEFAULT ((0)) NULL,
    [LockoutEndDateUtc]                       DATETIME       NULL,
    [LockoutEnabled]                          BIT            DEFAULT ((0)) NULL,
    [AccessFailedCount]                       INT            DEFAULT ((0)) NOT NULL,
    [CreateDate]                              DATETIME       NULL,
    CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE TABLE [dbo].[AspNetRoles] (
    --[Id]   NVARCHAR (128) NOT NULL,
    [Id]   INT            NOT NULL,
    [Name] NVARCHAR (256) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetRoles] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE TABLE [dbo].[AspNetUserRoles] (
    -- [UserId] NVARCHAR (128) NOT NULL,
    -- [RoleId] NVARCHAR (128) NOT NULL,
    [UserId] INT            NOT NULL,
    [RoleId] INT            NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUserRoles] PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
    CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetRoles_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[AspNetRoles] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_dbo.AspNetUserRoles_dbo.AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_RoleId]
    ON [dbo].[AspNetUserRoles]([RoleId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
    ON [dbo].[AspNetUserRoles]([UserId] ASC);
GO
CREATE TABLE [dbo].[AspNetUserLogins] (
    --[UserId]        NVARCHAR (128) NOT NULL,
    [UserId]        INT            NOT NULL,
    [LoginProvider] NVARCHAR (128) NOT NULL,
    [ProviderKey]   NVARCHAR (128) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUserLogins] PRIMARY KEY CLUSTERED ([UserId] ASC, [LoginProvider] ASC, [ProviderKey] ASC),
    CONSTRAINT [FK_dbo.AspNetUserLogins_dbo.AspNetUsers_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_UserId]
    ON [dbo].[AspNetUserLogins]([UserId] ASC);
GO

CREATE TABLE [dbo].[AspNetUserClaims] (
    [Id]         INT            IDENTITY (1, 1) NOT NULL,
    [ClaimType]  NVARCHAR (MAX) NULL,
    [ClaimValue] NVARCHAR (MAX) NULL,
    -- [UserId]    NVARCHAR (128) NOT NULL,
    [UserId]     INT            NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUserClaims] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.AspNetUserClaims_dbo.AspNetUsers_User_Id] FOREIGN KEY ([UserId]) REFERENCES [dbo].[AspNetUsers] ([Id]) ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_User_Id]
    ON [dbo].[AspNetUserClaims]([UserId] ASC);
GO

INSERT INTO AspNetUsers(Id, UserName, AcId, LcId, PasswordHash, SecurityStamp, CreateDate )
SELECT UserProfile.UserId, UserProfile.UserName, UserProfile.BaId, UserProfile.OfcId,
webpages_Membership.Password, webpages_Membership.PasswordSalt, CreateDate
FROM UserProfile
LEFT OUTER JOIN webpages_Membership ON UserProfile.UserId = webpages_Membership.UserId
GO

INSERT INTO AspNetRoles(Id, Name)
SELECT RoleId, RoleName
FROM webpages_Roles
GO

INSERT INTO AspNetUserRoles(UserId, RoleId)
SELECT UserId, RoleId
FROM webpages_UsersInRoles
GO

IF OBJECT_ID('dbo.webpages_OAuthMembership', 'U') IS NOT NULL
    DROP TABLE [dbo].[webpages_OAuthMembership]
GO

IF OBJECT_ID('dbo.webpages_UsersInRoles', 'U') IS NOT NULL
    DROP TABLE [dbo].[webpages_UsersInRoles]
GO
IF OBJECT_ID('dbo.webpages_Roles', 'U') IS NOT NULL
    DROP TABLE [dbo].[webpages_Roles]
GO
IF OBJECT_ID('dbo.UserProfile', 'U') IS NOT NULL
    DROP TABLE [dbo].[UserProfile]
GO
IF OBJECT_ID('dbo.webpages_Membership', 'U') IS NOT NULL
    DROP TABLE [dbo].[webpages_Membership]
GO

IF OBJECT_ID('dbo.__MigrationHistory', 'U') IS NOT NULL
    DROP TABLE [dbo].[__MigrationHistory]
GO

Have I missed something on configuring Identity 2.0 or is this a bug in Identity 2.0?

UPDATE 1: Removed the Global.asax.cs call to WebSecConfig. This had been masking a different issue with User.IsInRole.

Set breakpoint on var user in Home Controller UserRouting Action
Run app in debug and login in as "MyUser".
Step in and user gets set to "MyUser".
Step into var testrole and it throws 'Object reference not set to an instance of an object.'

Re-start and login again as "MyUser".
Step in and user gets set to "MyUser".
From Immediate Window enter User.IsInRole("XYZ") and it returns:

A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll
A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll
A first chance exception of type 'System.Web.HttpException' occurred in System.Web.dll

And opens a Warning dialogue box with:

HttpException was unhandled  
An unhandled exception of type 'System.Web.HttpException" occurred in System.Web.dll
Additional information: Unable to connect to SQL Server database.

My basic Database setup is correct or I wouldn't have been able to login. This leads me to believe there is a small discrepancy in how I ran the migration. Does anyone have an idea where I tripped up.

UPDATE 2: I refactored the code and migration script to use the default nvarchar for the Primary Keys and got the same results as Update 1.

UPDATE 3:

Web.Config:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />

    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <sectionGroup name="nwebsec">
      <!-- For information on how to configure NWebsec please visit: http://nwebsec.codeplex.com/wikipage?title=Configuration -->
      <section name="httpHeaderSecurityModule" type="NWebsec.Modules.Configuration.HttpHeaderSecurityConfigurationSection, NWebsec, Version=3.0.2.0, Culture=neutral, PublicKeyToken=3613da5f958908a1" requirePermission="false" />
    </sectionGroup>
    <sectionGroup name="elmah">
      <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
      <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
      <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
      <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup>

  <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
  <connectionStrings>
    <add name="MyApplication" connectionString="data source=.\SqlExpress;Integrated Security=SSPI;MultipleActiveResultSets = true;initial catalog=MyDb" providerName="System.Data.SqlClient" />
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="elmah.mvc.disableHandler" value="false" />
    <add key="elmah.mvc.disableHandleErrorFilter" value="false" />
    <add key="elmah.mvc.requiresAuthentication" value="true" />
    <add key="elmah.mvc.IgnoreDefaultRoute" value="false" />
    <add key="elmah.mvc.allowedRoles" value="Admin,CorpS" />
    <!--<add key="elmah.mvc.allowedUsers" value="*" />-->
    <add key="elmah.mvc.route" value="elmah" />
  </appSettings>
  <!--
    For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.

    The following attributes can be set on the <httpRuntime> tag.
      <system.Web>
        <httpRuntime targetFramework="4.5.1" />
      </system.Web>
  -->
  <system.web>
    <customErrors mode="Off" />
    <compilation debug="true" targetFramework="4.5.1" />
    <httpRuntime targetFramework="4.5" useFullyQualifiedRedirectUrl="true" maxRequestLength="100000" enableVersionHeader="false" />
    <!-- value is Kb, need to avoid crash with file upload of large files -->
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="15" />
    </authentication>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
    <!--<roleManager enabled="true" defaultProvider="simple">
      <providers>
        <clear />
        <add name="simple" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
      </providers>
    </roleManager>
    <membership defaultProvider="simple">
      <providers>
        <clear />
        <add name="simple" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
      </providers>
    </membership>-->
    <httpModules>
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
    </httpModules>
    <sessionState cookieName="My_SessionId" />
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

    </handlers>
    <modules>
      <add name="NWebsecHttpHeaderSecurityModule" type="NWebsec.Modules.HttpHeaderSecurityModule, NWebsec, Version=3.0.2.0, Culture=neutral, PublicKeyToken=3613da5f958908a1" />
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
      <remove name="RoleManager" />
    </modules>
    <httpProtocol>
      <customHeaders>
        <clear />
      </customHeaders>
     </httpProtocol>
     <security>
       <requestFiltering>
         <hiddenSegments>
           <add segment="NWebsecConfig" />
         </hiddenSegments>
       </requestFiltering>
      </security>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.6.1.0" newVersion="5.6.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.6.1.0" newVersion="5.6.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Spatial" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.6.1.0" newVersion="5.6.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly><assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /></dependentAssembly>
      <dependentAssembly><assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" /></dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    <dependentAssembly><assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /><bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" /></dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
      </dependentAssembly>
    </assemblyBinding>
    <!-- This prevents the Windows Event Log from frequently logging that HMAC1 is being used (when the other party needs it). -->
    <legacyHMACWarning enabled="0" />
    <!-- When targeting ASP.NET MVC 3, this assemblyBinding makes MVC 1 and 2 references relink
         to MVC 3 so libraries such as DotNetOpenAuth that compile against MVC 1 will work with it.
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
     -->
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
  <system.net>
    <defaultProxy enabled="true" />
    <settings>
      <!-- This setting causes .NET to check certificate revocation lists (CRL) 
           before trusting HTTPS certificates.  But this setting tends to not 
           be allowed in shared hosting environments. -->
      <!--<servicePointManager checkCertificateRevocationList="true"/>-->
    </settings>
  </system.net>
  <nwebsec>
    <httpHeaderSecurityModule xmlns="http://nwebsec.com/HttpHeaderSecurityModuleConfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="NWebsecConfig/HttpHeaderSecurityModuleConfig.xsd">
      <redirectValidation enabled="true"> <add allowedDestination="https://localhost/" /> </redirectValidation>
      <securityHttpHeaders>
        <x-Frame-Options policy="Deny" />
        <strict-Transport-Security max-age="365" />
        <x-Content-Type-Options enabled="true" />
      </securityHttpHeaders>
    </httpHeaderSecurityModule>
  </nwebsec>
  <elmah>
    <security allowRemoteAccess="false" />
  </elmah>

</configuration>

I needed to add <remove name="RoleManager" /> to the node as part of the MVC4-MVC5 migration, which I have now done.

Now I'm back to my original problem. User.IsInRole always returns false. If I run User.IsAuthenticated from the Immediate Window it returns

'System.Security.Principal.IPrincipal' does not contain a definition for 'IsAuthenticated' and no extension method 'IsAuthenticated' accepting a first argument of type 'System.Security.Principal.IPrincipal' could be found (are you missing a using directive or an assembly reference?)

I was able to get Identity.UserManager.IsInRole to work.

Home Controller: (revised to use UserManager)

using System;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using MyApplication.Models;
using System.Linq;
//using System.Web.Security;

namespace MyApplication.Controllers
{
  [Authorize]
  public class HomeController : Controller
  {
    private readonly MyDb _db = new MyDb();
    public UserManager<ApplicationUser> UserManager { get; private set; }
    public HomeController()  
      : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDb()))) { }
    public HomeController(UserManager<ApplicationUser> userManager)  
    { UserManager = userManager; }

    public ActionResult UserRouting()
    {
      var user = _db.Users.SingleOrDefault(u => u.UserName == User.Identity.Name);
      //var testrole = Roles.GetRolesForUser();  // for testing, remove from production
      if (UserManager.IsInRole(user.Id, "XYZ")) { // mycode }
      ...
     }
  }

This indicates that my database migration was correct.

I have dozens of calls to User.IsInRole in Controllers, Views, Custom Attributes, methods and classes in my app. To my understanding User.IsInRole is still a valid method in MVC5-EF6. If it is still considered a valid method rather than having to do a major refactoring of this legacy app I pose again my original question "why is User.IsInRole failing after SimpleMembership to Identity 2.0 migration"?

I've tested User.IsInRole in an Identity 1.0 MVC app and it works. I updated the app to Identity 2.0 and it still works. So I think it is safe to say that User.IsInRole is supported with Identity 2.0.

解决方案

After further investigation I found the problem to be that I never successfully logged in and since the User wasn't authenticated it caused the User.IsInRole to fail.

   var user = UserManager.Find(vM.UserName, vM.Password);

When you examine user in debug "MyUser" has been found but if you drill down further you find UserName is set to null.

User
    --{System.Data.Entity.DynamicProxies.ApplicationUser_...}   Identity.Models.ApplicationUser{System.Data.Entity.DynamicProxies.ApplicationUser_...} …
        base    {System.Data.Entity.DynamicProxies.ApplicationUser_...} Identity.Models.ApplicationUser {System.Data.Entity.DynamicProxies.ApplicationUser_...}
            base    {System.Data.Entity.DynamicProxies.ApplicationUser_...} Microsoft.AspNet.Identity.EntityFramework.IdentityUser  …
                base    {System.Data.Entity.DynamicProxies.ApplicationUser_...} Microsoft.AspNet.Identity.EntityFramework.IdentityUser<string,Microsoft.AspNet.Identity ...
                    AccessFailedCount   0           int
                    Claims              Count = 0   System.Collections.Generic.ICollection<Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim>  …
                    Email               null        string
                    EmailConfirmed      false       bool
                    Id                  "2"         string
                    LockoutEnabled      false       bool
                    LockoutEndDateUtc   null        System.DateTime?
                    Logins              Count = 0   System.Collections.Generic.ICollection<Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin> …
                    PasswordHash        "xxxxxx"    string
                    PhoneNumber         null        string
                    PhoneNumberConfirmed    false   bool
                    Roles               Count = 2   System.Collections.Generic.ICollection<Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole> …
                    SecurityStamp       ""          string
                    TwoFactorEnabled    false       bool
                    UserName            null        string

In ApplicationUser I overrode the UserName.

[StringLength(15)]
public new string UserName { get; set; }

When I removed the UserName override everything started working (I left UserName as a nvarchar(15), not null). The UserName override in ApplicationUser was the problem. If you want to change the nvarchar sizes you apparently just need to do that in the migration script.

Migrations from SimpleMembrship to Identity 2.0 works. User.IsInRole also works with Identity 2.0.

这篇关于将SimpleMembership数据库迁移到Identity 2后,User.IsInRole失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆