我在 GenerateUserIdentityAsync 方法中添加声明:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
userIdentity.AddClaim(new Claim(ClaimsStaticStrings.Inactivity, company.Inactivity.ToString()));
return userIdentity;
}
}
然后我尝试在帐户/登录方法中获取它:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
var result = await SignInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
int inactivity = Utils.GetInactivityFromIdentity(User.Identity);
Response.Cookies.Add(new HttpCookie("inactivity", inactivity.ToString()));
return RedirectToAction("Index", "Home");
}
}
public static int GetInactivityFromIdentity(IIdentity identity)
{
System.Security.Claims.ClaimsIdentity claims = (System.Security.Claims.ClaimsIdentity)identity;
var claim = claims.FindFirst(Models.ClaimsStaticStrings.Inactivity);
if (claim != null)
{
return int.Parse(claim.Value);
}
else
throw new Exception("Inactivity is not set");
}
它抛出异常“Inactivity is not set”。变量 'claims' 只有一个声明 - name
但是当我从任何其他页面(重定向后)调用 GetInactivityFromIdentity 方法时 - 它工作正常(并且声明中充满了所有设置的声明)。为什么会这样?
声明被序列化到 auth-cookie 中。在您通过身份验证重新加载页面之前,不会设置 Cookie。在您尝试从 cookie 访问声明时,HTTP 请求中没有 cookie -
SignInManager
只会在请求完成时设置 cookie,但不会在请求完成后立即设置。您确实需要一个重定向/页面重新加载周期来获取可用的 cookie 和声明。
您必须以某种方式获得
inactivity
价值,而不是通过声明,而是在您登录用户时从您的数据存储中获得。
无法访问登录用户声明的原因是登录过程中设计的事件顺序 - .Net 问题。 当您执行调用 SignInManager.SignIn() 时,事件顺序将带您完成项目的扩展类 ApplicationSignInManager,它派生自 SingInManager - 在其中您会发现一个名为 CreateUserIdentityAsync 的覆盖方法,它会被触发通过登录调用。 在这个方法中,用户身份声明被创建并返回(通过调用 GenerateUserIdentityAsync),只有在登录过程的后期才能访问它们。 这里的工作是在 ApplicationSignInManager 类中创建一个名为 AppUserClaims 的 ClaimsIdentity 类型的公共属性,并使用它来存储用户身份声明值,然后再将它们检索到登录流程。
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
var iClaims = user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
AppUserClaims = iClaims.Result;
return iClaims;
}
一旦你存储了这个属性的声明,回到登录方法内部,你就可以像下面这样访问它——记住声明值总是字符串类型:
string YourX = SignInManager.AppUserClaims.FindFirst("YourX").Value;