我是ASP.NET身份的新手,我仍然试图了解它是如何工作的。不幸的是,我发现我尝试过的许多教程都是针对Identity 1.0的,而我正在尝试使用Identity 2.0。
我面临的最大问题是我认为很简单,但事实证明并非如此。我要做的是使用现有数据库和现有用户表。目前我所能做的就是让Identity创建自己的表来存储用户数据。我不想使用Entity Framework,但是我很难将Entity Framework与Identity 2.0分开。
虽然我的情况是我正在使用SQL Server,但我想我会尝试在此链接上实现MySQL的自定义提供程序:http://www.asp.net/identity/overview/extensibility/implementing-a-custom-mysql-aspnet-identity-storage-provider和https://github.com/raquelsa/AspNet.Identity.MySQL。这似乎只在身份1下工作。似乎有一个较新的,但使用实体框架。我也试过https://github.com/ILMServices/RavenDB.AspNet.Identity。
对于我尝试的所有内容,我会遇到以下问题:
var manager = new IdentityUserManager(new UserStore<IdentityUser>(context.Get<ApplicationDbContext>()));
我面临的问题是我需要根据RavenDB的说明删除ApplicaitonDbContext类,但是我不知道该放入什么内容。
我得到的错误是:
非泛型类型'AspNet.Identity.MySQL.UserStore'不能与类型参数一起使用
和
找不到类型或命名空间名称'ApplicationDbContext'(您是否缺少using指令或程序集引用?)
第二个错误是预期的,但是我不确定在这行代码中使用什么。有没有人在没有使用Entity Framework的情况下实现自定义提供程序的经验?
感谢。
更新1:
我尝试了以下教程[http://aspnetguru.com/customize-authentication-to-your-own-set-of-tables-in-asp-net-mvc-5/],但它似乎不完整,在完全遵循教程时出现编译或运行时错误。我还有一些问题......
将“ApplicationUser”的所有实例替换为“User”时,IdentityConfig.cs中的以下行出现问题
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<MyDbContext>()));
将ApplicationUser更改为User会产生以下错误
“WebApplicationTest2.Models.User”类型不能在泛型类型或方法“Microsoft.AspNet.Identity.EntityFramework.UserStore”中用作类型参数“TUser”。没有从“WebApplicationTest2.Models.User”到“Microsoft.AspNet.Identity.EntityFramework.IdentityUser”的隐式引用转换。
我也很难弄清楚如何使用用户管理器和许多ASync方法。以下行不起作用:
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
在AccountController.cs中出现以下错误:
“Microsoft.Owin.Security.IAuthenticationManager.SignIn(Microsoft.Owin.Security.AuthenticationProperties,params System.Security.Claims.ClaimsIdentity [])”的最佳重载方法匹配包含一些无效参数。
'WebApplicationTest2.Models.User'不包含'GenerateUserIdentityAsync'的定义,并且没有可以找到接受类型为'WebApplicationTest2.Models.User'的第一个参数的扩展方法'GenerateUserIdentityAsync'(您是否缺少using指令或汇编参考?)
答案 0 :(得分:37)
在您的示例中,您似乎想要用其他内容替换DbContext
但我相信实际上,您需要将您的工作重点放在更高的位置。
该框架有一个类UserManager
,它负责管理用户及其相关信息,但不存储。当它想要存储用户(或其相关信息)时,默认使用提供的UserStore<IdentityUser>
,它知道如何使用IdentityUser
将DbContext
实例存储在数据库中。
在2.0框架中,身份存储的各个部分被分成几个接口。提供的默认实现UserStore<IdentityUser>
实现了其中的几个接口,并使用DBContext
将数据全部存储在数据库中。
如果你看看基于UserStore的默认提供的实体框架的定义,你可以看到它实现了许多这些小接口:
public class UserStore<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> : IUserLoginStore<TUser, TKey>,
IUserClaimStore<TUser, TKey>, IUserRoleStore<TUser, TKey>, IUserPasswordStore<TUser, TKey>,
IUserSecurityStampStore<TUser, TKey>, IQueryableUserStore<TUser, TKey>, IUserEmailStore<TUser, TKey>,
IUserPhoneNumberStore<TUser, TKey>, IUserTwoFactorStore<TUser, TKey>, IUserLockoutStore<TUser, TKey>,
IUserStore<TUser, TKey>, IDisposable
where TUser : IdentityUser<TKey, TUserLogin, TUserRole, TUserClaim>
where TRole : IdentityRole<TKey, TUserRole>
where TKey : Object, IEquatable<TKey>
where TUserLogin : new(), IdentityUserLogin<TKey>
where TUserRole : new(), IdentityUserRole<TKey>
where TUserClaim : new(), IdentityUserClaim<TKey>
由于您根本不想使用Entity Framework,因此您需要提供自己的一些关键接口实现,这些接口会将这些数据存储在您希望存储数据的位置。主界面是IUserStore<Tuser,TKey>
。这定义了用于存储具有特定类型的密钥的用户的合同。如果您只想存储用户而没有其他信息,那么您可以实现此界面,然后将您的实现传递给UserManager
,您应该很高兴。
虽然您可能希望为用户提供密码,角色,登录等,但这不太可能。如果是这样,那么您需要使实现IUserStore<Tuser,TKey>
的类也实现IUserPasswordStore<TUser, TKey>
,IRoleStore<TRole, TKey>
和IUserClaimStore<TUser, TKey>
。
您可以找到所有接口on MSDN here
的列表根据您要使用的位,您需要实现这些接口。
您可能还需要为Entity framework already out of the box定义自己的Identity*
类版本。因此,您需要自己的IdentityUser
类来表示您要存储的用户,并IdentityUserClaim
用于用户声明。我自己也没有这样做,所以我不确定,但我的感觉是你必须这样做。
Scott Allen对模型的各个部分有一个good article可能有用。
至于你对这一行的问题:
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, await user.GenerateUserIdentityAsync(UserManager));
有一个名为GenerateUserIdentityAsync
的方法,它在Applicationuser
上定义,扩展了IdentityUser
。它在我相信的模板项目中定义,看起来像这样:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
UserManager<ApplicationUser> 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;
}
}
由于您不再使用实体框架IdentityUser
,您需要定义一个类似的方法或您自己的User
类,或者以其他方式实现相同的功能(比如只调用{{ 1}}代替)
答案 1 :(得分:1)
我对身份本身很陌生。 您的用户实体是否实现了IUser接口? e.g。
public partial class User : IUser<Guid> //Whatever your key is
{
public Task<ClaimsIdentity> GenerateUserIdentityAsync(ApplicationUserManager manager)
{
return Task.FromResult(GenerateUserIdentity(manager));
}
public ClaimsIdentity GenerateUserIdentity(ApplicationUserManager manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = manager.CreateIdentity<User, Guid>(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
然后要登录,您可以拨打以上电话:
public async Task SignInAsync(User user, bool isPersistent)
{
var userIdentity = await user.GenerateUserIdentityAsync(UserManager);
AuthenticationManager.SignIn(
new AuthenticationProperties
{
IsPersistent = isPersistent
},
userIdentity
);
}
答案 2 :(得分:1)
我认为最近已在ApplicationUser
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
从AccountController
- &gt;这样调用它GetExternalLogin
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
CookieAuthenticationDefaults.AuthenticationType);