Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 成功登录时添加声明_C#_Asp.net Mvc_Asp.net Identity - Fatal编程技术网

C# 成功登录时添加声明

C# 成功登录时添加声明,c#,asp.net-mvc,asp.net-identity,C#,Asp.net Mvc,Asp.net Identity,我需要在用户成功登录后添加对用户身份的声明。这就是我认为需要实现的地方: public async Task<ActionResult> Login(LoginViewModel model, string returnUrl, string myClaimValue) { if (!ModelState.IsValid) { return View(model); } var result = await SignInManager.Passw

我需要在用户成功登录后添加对用户身份的声明。这就是我认为需要实现的地方:

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);
   }
}
公共异步任务登录(LoginViewModel模型、字符串returnUrl、字符串myClaimValue)
{
如果(!ModelState.IsValid)
{
返回视图(模型);
}
var result=await-SignInManager.PasswordSignInAsync(model.UserName、model.Password、model.RememberMe、shouldllockout:false);
开关(结果)
{
案例标志状态成功:
UserManager.AddClaim(User.Identity.GetUserId(),新声明(“MyClaim”,myClaimValue));
返回重定向到本地(returnUrl);
案例标志状态锁定输出:
返回视图(“锁定”);
案例标志状态。要求验证:
return RedirectToAction(“SendCode”,new{ReturnUrl=ReturnUrl,RememberMe=model.RememberMe});
案例信号状态故障:
违约:
AddModelError(“,”登录尝试无效“);
返回视图(模型);
}
}
我认为这是正确的方法,但是调用
User.Identity.GetUserId()
会引发异常。看起来像是
用户。成功登录不会更新身份。代替这种现实,对于我来说,获得新登录的用户id以便添加索赔的最佳方式是什么


还是我做错了?

这将把声明存储到数据库
UserManager.AddClaim(User.Identity.GetUserId(),newclaim(“MyClaim”,myClaimValue))

如果您希望在登录用户登录时将声明与他关联,则必须覆盖
SignInManager的
SignInAsync
方法

public override async Task SignInAsync(ApplicationUser user, bool isPersistent, bool rememberBrowser) { var userIdentity = await CreateUserIdentityAsync(user); // your code here userIdentity.AddClaim(new Claim(ClaimTypes.Gender, "male")); // AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie); if (rememberBrowser) { var rememberBrowserIdentpublic override async Task SignInAsync(ApplicationUser user, bool isPersistent, bool rememberBrowser)
{
    var userIdentity = await CreateUserIdentityAsync(user);

    // add your claims here
    userIdentity.AddClaim(new Claim(ClaimTypes.Gender, "male"));
    //

    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie);
    if (rememberBrowser)
    {
        var rememberBrowserIdentity = AuthenticationManager.CreateTwoFactorRememberBrowserIdentity(ConvertIdToString(user.Id));
        AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity, rememberBrowserIdentity);
    }
    else
    {
        AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity);
    }
}

必须在触发SignInManager.PasswordSignInAsync之前设置其他声明。这可以通过自定义ClaimSideEntityFactory完成:

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;
    }
}

@约翰·桑德斯,谢谢!这很有道理。我越想这件事,就越觉得我做错了。在我看来,声明是识别用户的东西。我的目标是存储一些关于用户的真实数据,这些数据是在登录时在客户机上计算的。此数据不应存储在数据库中,但应在登录用户登录时与该用户关联。声明不仅仅用于标识用户。它们是用户断言为真的一组“命题”。例如,“我在以下角色中”是一个合理的说法。@JohnSaunders感谢您的解释。这是有道理的,我认为我使用它们的方式是合理的。我明白了,谢谢。问题是,当我试图在其他控制器中访问该声明时,它并不存在。此外,当我像上面所做的那样创建一个新的
claiminentity
时,
User.Identity.IsAuthenticated
为false。我不确定问题是否在于
User.Identity
似乎没有完全初始化,或者在创建新标识后,我没有对其进行任何操作。@itslitlejohn这与您所说的不一样,正在更新答案。感谢您的更新。我将尽快对此进行测试。我最终只使用了session变量。这仍然不起作用,因为我的声明值是从登录请求动态传入的。因为这似乎很难处理索赔,我认为这是错误的方法。如果我错了,请纠正我。问题不在于如何在成功登录后添加声明吗?回答“必须在”登录之前设置,而不提供任何支持该语句的内容,对阅读答案的人来说并没有真正的帮助。@MladenB。您在登录之前将索赔工厂设置为signinmanager,以便在发生登录时使用您准备的工厂。你是对的,这与问题有关,但与问题的答案无关。
UserManager.ClaimsIdentityFactory = new ApplicationClaimsIdentityFactory() 
        { 
            MyClaimValue = loginModel.MyClaimValue
        };
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);