这是这个问题的延续。
如果我覆盖userManager:
public class NHibernateAspnetUserManager<TUser> : UserManager<TUser> where TUser : IdentityUser
{
public NHibernateAspnetUserManager(IUserStore<TUser> store) : base(store)
{
}
public override Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType)
{
var identity = new ClaimsIdentity();
identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
return Task.FromResult(identity);
}
}
这不会引发任何错误,但不会让用户登录(日志过程会发生,但@Request.IsAuthenticated将始终返回false)。如果我不覆盖它,那么我会得到另一个问题中描述的"System.Security.Commands.Claim..ctor"错误。为了解决这个问题,我自己的用户商店实现了IUserClaimStore,但只是返回一个新的声明列表。
我不确定默认的用户管理器在不同的情况下会做什么。我猜它设置了某种形式的声明身份对象,允许MVC识别登录的人
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent}, identity);
编辑
找出发生ctor错误的原因。用户对象返回时没有ID,因此默认的UserManager出现问题。修复了这个问题,并使用了默认的UserManager,它现在不再抛出错误,但仍然不会让用户登录。据我所知,它返回的标识对象看起来不错。
进一步注意
所以我安装了VS2013,并复制了商店和NHibernate回购,所有这些都是第一次工作。我只能假设在VS2012中创建它、更新MVC5和在VS2013中执行它之间有一些明显的区别。
因此,主要问题是您的方法中不尊重身份验证类型,您需要为DefaultAuthenticationType.ApplicationCookie创建ClaimsIdentity,以下是默认声明工厂所做的:
public override Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType)
{
var id = new ClaimsIdentity(authenticationType, UserNameClaimType, RoleClaimType);
id.AddClaim(new Claim(UserIdClaimType, ConvertIdToString(user.Id), ClaimValueTypes.String));
id.AddClaim(new Claim(UserNameClaimType, user.UserName, ClaimValueTypes.String));
我在使用ASP.NET 4.5实现自定义标识时也遇到过同样的问题。真正的问题是在Claims集合中添加null值(参见注释):
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new AppUser { UserName = model.UserName };
// after the UserManager creates a user, all the properties of
// AppUser except "UserName" are automatically discarded
var result = await UserManager.CreateAsync(new AppUser
{
UserRealName = model.UserRealName,
UserName = model.UserName,
Password = model.Password
}, model.Password);
if (result.Succeeded)
{
// So we need to re-get the new user
user = AppUser.GetByName(model.UserName);
await SignInAsync(user, false); // otherwise here we will add null values ...
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
return View(model);
}
private async Task SignInAsync(AppUser user, Boolean isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
var identity = await UserManager.CreateIdentityAsync(user,
DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties // ... into the list of
// claims for all AppUser properties except UserName
{ IsPersistent = isPersistent }, identity);
}