Using a 斯特凡·塞布拉克的回答和本·福斯特的精彩博客文章ASP.NET 身份被剥离我提出了以下解决方案,并将其应用于 ASP.NET Identity2.0由 Visual Studio 2013 生成AccountController
.
该解决方案使用整数作为用户的主键,并且还允许获取当前登录用户的 ID,而无需访问数据库。
以下是您需要遵循的步骤:
1.创建自定义用户相关类
默认情况下,AccountController
使用类,这些类正在使用string
,作为主键的一种类型。我们需要创建以下类,它将使用int
反而。我已在一个文件中定义了以下所有类:AppUser.cs
public class AppUser :
IdentityUser<int, AppUserLogin, AppUserRole, AppUserClaim>,
IUser<int>
{
}
public class AppUserLogin : IdentityUserLogin<int> { }
public class AppUserRole : IdentityUserRole<int> { }
public class AppUserClaim : IdentityUserClaim<int> { }
public class AppRole : IdentityRole<int, AppUserRole> { }
拥有一个自定义的 ClaimsPrincipal 也很有用,它可以轻松暴露用户的 ID
public class AppClaimsPrincipal : ClaimsPrincipal
{
public AppClaimsPrincipal( ClaimsPrincipal principal ) : base( principal )
{ }
public int UserId
{
get { return int.Parse(this.FindFirst( ClaimTypes.Sid ).Value); }
}
}
2. 创建自定义IdentityDbContext
我们的应用程序的数据库上下文将扩展IdentityDbContext
,它默认实现所有与身份验证相关的 DbSet。即使DbContext.OnModelCreating
是一个空方法,我不确定IdentityDbContext.OnModelCreating
,所以重写时,记得调用base.OnModelCreating( modelBuilder )
AppDbContext.cs
public class AppDbContext :
IdentityDbContext<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>
{
public AppDbContext() : base("DefaultConnection")
{
// Here use initializer of your choice
Database.SetInitializer( new CreateDatabaseIfNotExists<AppDbContext>() );
}
// Here you define your own DbSet's
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating( modelBuilder );
// Here you can put FluentAPI code or add configuration map's
}
}
3. 创建自定义UserStore
and UserManager
,上面将使用
AppUserStore.cs
public interface IAppUserStore : IUserStore<AppUser, int>
{
}
public class AppUserStore :
UserStore<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>,
IAppUserStore
{
public AppUserStore() : base( new AppDbContext() )
{
}
public AppUserStore(AppDbContext context) : base(context)
{
}
}
AppUserManager.cs
public class AppUserManager : UserManager<AppUser, int>
{
public AppUserManager( IAppUserStore store ) : base( store )
{
}
}
4. 修改AccountController
使用您的自定义类
全部更改UserManager
to AppUserManager
, UserStore
to AppUserStore
等等。举个这个构造函数的例子:
public AccountController()
: this( new AppUserManager( new AppUserStore( new AppDbContext() ) ) )
{
}
public AccountController(AppUserManager userManager)
{
UserManager = userManager;
}
5. 添加用户 ID 作为声明ClaimIdentity
存储在cookie中
在第 1 步中,我们创建了AppClaimsPrincipal
,它公开了从中取出的 UserIdClaimType.Sid
。但是,要使此声明可用,我们需要在用户登录时添加它。在AccountController
a SingInAsync
方法负责登录。我们需要向该方法添加一行,以添加声明。
private async Task SignInAsync(AppUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// Extend identity claims
identity.AddClaim( new Claim( ClaimTypes.Sid, user.Id.ToString() ) );
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
6. 创建一个BaseController
with a CurrentUser
财产
要轻松访问控制器中当前登录的用户 ID,请创建一个摘要BaseController
,您的控制器将从中派生。在里面BaseController
, 创建一个CurrentUser
如下:
public abstract class BaseController : Controller
{
public AppClaimsPrincipal CurrentUser
{
get { return new AppClaimsPrincipal( ( ClaimsPrincipal )this.User ); }
}
public BaseController()
{
}
}
7. 继承你的控制器BaseController
享受
从现在开始,您可以使用CurrentUser.UserId
在您的控制器中访问当前登录用户的 ID,而无需访问数据库。您可以使用它来仅查询属于用户的对象。
您不必关心用户主键的自动生成 - 毫不奇怪,实体框架在创建表时默认使用 Identity 作为整数主键。
Warning!请记住,如果您在已发布的项目中实现它,则对于已登录的用户ClaimsType.Sid
将不存在并且FindFirst
将返回 nullAppClaimsPrincipal
。您需要强制注销所有用户或处理这种情况AppClaimsPrincipal