当前位置 主页 > 服务器问题 > win服务器问题汇总 >

    ASP.NET Cookie是怎么生成的(推荐)

    栏目:win服务器问题汇总 时间:2020-01-29 20:20

    可能有人知道Cookie的生成由machineKey有关,machineKey用于决定Cookie生成的算法和密钥,并如果使用多台服务器做负载均衡时,必须指定一致的machineKey用于解密,那么这个过程到底是怎样的呢?

    如果需要在.NET Core中使用ASP.NET Cookie,本文将提到的内容也将是一些必经之路。

    抽丝剥茧,一步一步分析
    首先用户通过AccountController->Login进行登录:

    //
    // POST: /Account/Login
    public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
    {
     if (!ModelState.IsValid)
     {
     return View(model);
     }
    
     var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
     switch (result)
     {
     case SignInStatus.Success:
      return RedirectToLocal(returnUrl);
     // ......省略其它代码
     }
    }

    它调用了SignInManager的PasswordSignInAsync方法,该方法代码如下(有删减):

    public virtual async Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
    {
     // ...省略其它代码
     if (await UserManager.CheckPasswordAsync(user, password).WithCurrentCulture())
     {
     if (!await IsTwoFactorEnabled(user))
     {
      await UserManager.ResetAccessFailedCountAsync(user.Id).WithCurrentCulture();
     }
     return await SignInOrTwoFactor(user, isPersistent).WithCurrentCulture();
     }
     // ...省略其它代码
     return SignInStatus.Failure;
    }

    想浏览原始代码,可参见官方的Github链接:

    https://github.com/aspnet/AspNetIdentity/blob/master/src/Microsoft.AspNet.Identity.Owin/SignInManager.cs#L235-L276

    可见它先需要验证密码,密码验证正确后,它调用了SignInOrTwoFactor方法,该方法代码如下:

    private async Task<SignInStatus> SignInOrTwoFactor(TUser user, bool isPersistent)
    {
     var id = Convert.ToString(user.Id);
     if (await IsTwoFactorEnabled(user) && !await AuthenticationManager.TwoFactorBrowserRememberedAsync(id).WithCurrentCulture())
     {
     var identity = new ClaimsIdentity(DefaultAuthenticationTypes.TwoFactorCookie);
     identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, id));
     AuthenticationManager.SignIn(identity);
     return SignInStatus.RequiresVerification;
     }
     await SignInAsync(user, isPersistent, false).WithCurrentCulture();
     return SignInStatus.Success;
    }

    该代码只是判断了是否需要做双重验证,在需要双重验证的情况下,它调用了AuthenticationManager的SignIn方法;否则调用SignInAsync方法。SignInAsync的源代码如下:

    public virtual async Task SignInAsync(TUser user, bool isPersistent, bool rememberBrowser)
    {
     var userIdentity = await CreateUserIdentityAsync(user).WithCurrentCulture();
     // Clear any partial cookies from external or two factor partial sign ins
     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);
     }
    }