何时可以索赔

问题描述 投票:0回答:2

我在 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 方法时 - 它工作正常(并且声明中充满了所有设置的声明)。为什么会这样?

c# asp.net-identity claims-based-identity claims
2个回答
1
投票

声明被序列化到 auth-cookie 中。在您通过身份验证重新加载页面之前,不会设置 Cookie。在您尝试从 cookie 访问声明时,HTTP 请求中没有 cookie -

SignInManager
只会在请求完成时设置 cookie,但不会在请求完成后立即设置。您确实需要一个重定向/页面重新加载周期来获取可用的 cookie 和声明。

您必须以某种方式获得

inactivity
价值,而不是通过声明,而是在您登录用户时从您的数据存储中获得。


0
投票

无法访问登录用户声明的原因是登录过程中设计的事件顺序 - .Net 问题。 当您执行调用 SignInManager.SignIn() 时,事件顺序将带您完成项目的扩展类 ApplicationSignInManager,它派生自 SingInManager - 在其中您会发现一个名为 CreateUserIdentityAsync 的覆盖方法,它会被触发通过登录调用。 在这个方法中,用户身份声明被创建并返回(通过调用 GenerateUserIdentityAsync),只有在登录过程的后期才能访问它们。 这里的工作是在 ApplicationSignInManager 类中创建一个名为 AppUserClaimsClaimsIdentity 类型的公共属性,并使用它来存储用户身份声明值,然后再将它们检索到登录流程。

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;
© www.soinside.com 2019 - 2024. All rights reserved.