我有一个ASP.NET身份2实现(没有用户数据,只有基表),我有一个类型为UNIQUEIDENTIFIER的userId。
应用程序首先是代码,我使用的是EF6。
这里是DDL:
CREATE TABLE [dbo].[AspNetUsers] (
[Id] UNIQUEIDENTIFIER NOT NULL,
[FirstName] NVARCHAR (MAX) NULL,
[LastName] NVARCHAR (MAX) NULL,
[Email] NVARCHAR (256) NULL,
[EmailConfirmed] BIT NOT NULL,
[PasswordHash] NVARCHAR (MAX) NULL,
[SecurityStamp] NVARCHAR (MAX) NULL,
[PhoneNumber] NVARCHAR (MAX) NULL,
[PhoneNumberConfirmed] BIT NOT NULL,
[TwoFactorEnabled] BIT NOT NULL,
[LockoutEndDateUtc] DATETIME NULL,
[LockoutEnabled] BIT NOT NULL,
[AccessFailedCount] INT NOT NULL,
[UserName] NVARCHAR (256) NOT NULL,
[SubjectId] INT DEFAULT ((0)) NOT NULL,
[SubjectIds] VARCHAR (50) NULL,
[OrganizationId] INT DEFAULT ((0)) NOT NULL,
[OrganizationIds] VARCHAR (50) NULL,
[RoleId] INT DEFAULT ((0)) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
ON [dbo].[AspNetUsers]([UserName] ASC);
我知道GUID创建正常是正常的GUID。
有人可以告诉我如何创建一个新的序列GUID吗?
请注意
我正在寻找使用ASP.Net Identity 2的正确方法。特别是我想知道Identity 2 UserManager等是否需要进行任何更改。
答案 0 :(得分:3)
我终于能够构建项目并运行它。使用Fluent API创建后,newsequentialid()
被分配给ID字段:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>().Property(t => t.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<CustomUserRole>().HasKey(x => new
{
x.RoleId,
x.UserId
});
modelBuilder.Entity<CustomUserLogin>().HasKey(x => new
{
x.UserId,
x.ProviderKey,
x.LoginProvider
});
}
结果是SQL表编写为:
/****** Object: Table [dbo].[AspNetUsers] Script Date: 4/11/2015 3:40:51 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUsers](
[Id] [uniqueidentifier] NOT NULL,
[Email] [nvarchar](256) NULL,
[EmailConfirmed] [bit] NOT NULL,
[PasswordHash] [nvarchar](max) NULL,
[SecurityStamp] [nvarchar](max) NULL,
[PhoneNumber] [nvarchar](max) NULL,
[PhoneNumberConfirmed] [bit] NOT NULL,
[TwoFactorEnabled] [bit] NOT NULL,
[LockoutEndDateUtc] [datetime] NULL,
[LockoutEnabled] [bit] NOT NULL,
[AccessFailedCount] [int] NOT NULL,
[UserName] [nvarchar](256) NOT NULL,
CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[AspNetUsers] ADD DEFAULT (newsequentialid()) FOR [Id]
GO
必须更改其他实体类型:
public class ApplicationUser : IdentityUser<Guid, CustomUserLogin, CustomUserRole,
CustomUserClaim>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override Guid Id { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, Guid> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class CustomUserRole : IdentityUserRole<Guid> { }
public class CustomUserClaim : IdentityUserClaim<Guid> { }
public class CustomUserLogin : IdentityUserLogin<Guid> { }
public class CustomRole : IdentityRole<Guid, CustomUserRole>
{
public CustomRole() { }
public CustomRole(string name) { Name = name; }
}
public class CustomUserStore : UserStore<ApplicationUser, CustomRole, Guid,
CustomUserLogin, CustomUserRole, CustomUserClaim>
{
public CustomUserStore(ApplicationDbContext context)
: base(context)
{
}
}
public class CustomRoleStore : RoleStore<CustomRole, Guid, CustomUserRole>
{
public CustomRoleStore(ApplicationDbContext context)
: base(context)
{
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole,
Guid, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
在Startup.Auth.cs中,我改变了
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator
.OnValidateIdentity<ApplicationUserManager, ApplicationUser, Guid>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentityCallback: (manager, user) =>
user.GenerateUserIdentityAsync(manager),
getUserIdCallback: (id) => new Guid(id.GetUserId()))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
在IdentityConfig.cs中,我更改了ApplicationUserManager
下面:
public class ApplicationUserManager : UserManager<ApplicationUser, Guid>
{
public ApplicationUserManager(IUserStore<ApplicationUser, Guid> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(
new CustomUserStore(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames manager.UserValidator = new UserValidator<ApplicationUser>(manager)
manager.UserValidator = new UserValidator<ApplicationUser, Guid>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
并且
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser, Guid>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser, Guid>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser, Guid>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
// Configure the application sign-in manager which is used in this application.
public class ApplicationSignInManager : SignInManager<ApplicationUser, Guid>
在ManageController.cs中,我添加了
public class ManageController : Controller
{
private ApplicationSignInManager _signInManager;
private ApplicationUserManager _userManager;
private Guid userGuidId;
public ManageController()
{
userGuidId= new Guid(User.Identity.GetUserId());
}
在我看到userGuidId
userId
我必须在这里使用ToString()
:
BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userGuidId.ToString())
在帐户控制器中,我似乎只是改变了
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
Guid GuidUserId = new Guid(userId);
if (userId == null || code == null)
{
return View("Error");
}
var result = await UserManager.ConfirmEmailAsync(GuidUserId, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
答案 1 :(得分:1)
首先创建基于“IdentityUser”类的非通用版本......
public class AppUserClaim : IdentityUserClaim<Guid> { }
public class AppUserLogin : IdentityUserLogin<Guid> { }
public class AppUserRole : IdentityUserRole<Guid> { }
...然后IdentityRole
和UserStore
以及`UserManager ...
public class AppRole : IdentityRole<Guid, AppUserRole>
{
}
public class AppUserStore : UserStore<AppUser, AppRole, Guid, AppUserLogin, AppUserRole, AppUserClaim>
{
public AppUserStore(DbContext context)
: base(context)
{
}
}
public class AppUserManager : UserManager<AppUser, Guid>
{
public AppUserManager(IUserStore<AppUser, Guid> store)
: base(store)
{
}
}
...最后是IdentityDbContext
...
public class AppIdentityContext : IdentityDbContext<AppUser, AppRole, Guid, AppUserLogin, AppUserRole, AppUserClaim>
{
public AppIdentityContext()
: base("name=AspNetIdentity")
{
}
}
在所有这些新类中,您会注意到基类使用Identity类的通用版本,我们正在使用AppUserClaim
,AppUserLogin
,AppUserRole
和{{1}代替身份对应物。
对于用户,我们创建了一个名为AppRole
的类,该类将派生自AppUser
:
IdentityUser
在构造函数中,我们使用public class AppUser : IdentityUser<Guid, AppUserLogin, AppUserRole, AppUserClaim>
{
[DllImport("rpcrt4.dll", SetLastError = true)]
private static extern int UuidCreateSequential(out Guid guid);
private Guid _id;
public AppUser()
{
UuidCreateSequential(out _id);
}
/// <summary>
/// User ID (Primary Key)
/// </summary>
public override Guid Id
{
get { return _id; }
set { _id = value; }
}
}
函数创建一个新ID,并通过UuidCreateSequential
属性返回该ID。我想在数据库中设置Id
列以使用Id
作为默认值并使用它而不是newsequentialid()
,但我还没有解决这个问题。
在控制器操作中使用:
DllImport
有几点需要注意:
如果您使用的是现有数据库,即使用SQL脚本创建的数据库,public async Task<ActionResult> ActionName()
{
AppIdentityContext dbContext = new AppIdentityContext();
AppUserStore store = new AppUserStore(dbContext);
AppUserManager manager = new AppUserManager(store);
AppUser user = new AppUser { UserName = "<name>", Email = "<email>" };
await manager.CreateAsync(user);
return this.View();
}
中的Id
列为AspNetUsers
,则需要更改跟随列到nvarchar
:
在ASP.NET MVC控制器中的uniqueidentifier
接口上使用GetUserId
扩展方法,即IIdentity
,将返回this.User.Identity.GetUserId()
所以您将拥有在将返回值转换为字符串时使用以下内容:
string
此方法有一个通用版本,但它下面使用new Guid(this.User.Identity.GetUserId())
,并且要求在实现Convert.ChangeType
和IConvertable
中传递的值不会。
我无法对此进行全面测试,但希望如果它不能完全满足您的需求,它将提供有用的基础。
更新#1 :以下是我完成的步骤:
添加以下NuGet包
将所有代码示例添加到Guid
文件夹中名为Identity.cs
的文件
注意:排除控制器操作示例..这将在步骤#6中完成
从App_Start
web.config
web.config
添加新的连接字符串
AspNetIdentity
上的Index
操作,并替换HomeController
和<name>
部分<email>
添加到SQL Server 如果使用选择了个人用户帐户身份验证选项的ASP.NET MVC模板,则会出现一些必须修复的错误。这些主要集中在将AspNetIdentity
类的引用更改为基于IdentityUser*
的新类,并替换对AppUser*
的调用以使用我原始答案中步骤#2中提供的代码示例。< / p>
答案 2 :(得分:0)
这对我来说是有用的,可以使角色和用户类型为Guid的ID字段在默认值或绑定中具有newsequentialid()
:
将以下代码添加到 ApplicationDbContext 类:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>().Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<ApplicationRole>().Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
Add-Migration Initial
Update-Database
警告:这将删除数据库中角色的所有用户