我需要在用户成功登录后添加对用户身份的声明。这是我认为需要发生的地方:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl, string myClaimValue)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
UserManager.AddClaim(User.Identity.GetUserId(), new Claim("MyClaim", myClaimValue));
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
我认为这是正确的方法,但对User.Identity.GetUserId()
的调用会引发异常。看起来User.Identity
没有被成功登录更新。代替这个现实,我最好的方式是获得新签名的用户ID,以便我可以添加声明吗?
或者我这样做错了吗?
答案 0 :(得分:4)
必须在触发SignInManager.PasswordSignInAsync之前设置其他声明。这可以通过自定义ClaimsIdentityFactory来完成:
public class ApplicationClaimsIdentityFactory : ClaimsIdentityFactory<ApplicationUser>
{
// This claim value is taken from Login View
public static readonly string MyClaimKey = "app:MyClaimKey";
public string MyClaimValue { get; set; }
public async override Task<ClaimsIdentity> CreateAsync(UserManager<ApplicationUser, string> manager, ApplicationUser user, string authenticationType)
{
var identity = await base.CreateAsync(manager, user, authenticationType);
identity.AddClaim(new Claim(MyClaimKey, MyClaimValue));
return identity;
}
}
在登录步骤之前应用此工厂:
UserManager.ClaimsIdentityFactory = new ApplicationClaimsIdentityFactory()
{
MyClaimValue = loginModel.MyClaimValue
};
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
答案 1 :(得分:3)
这会将声明存储到数据库UserManager.AddClaim(User.Identity.GetUserId(), new Claim("MyClaim", myClaimValue));
如果您只想在登录时与登录用户关联声明,则必须覆盖SignInAsync
的{{1}}方法
SignInManager