我将自定义声明(例如用户的真实姓名)存储在ASP.NET标识cookie中,以避免对每个请求进行不必要的数据库查询.至少这是我假设这段代码正在做的事情:
var identity = await user.GenerateUserIdentityAsync(UserManager);
identity.AddClaim(new Claim(ClaimTypes.GivenName, user.FirstName)));
// etc.
AuthenticationManager.SignIn(new AuthenticationProperties {IsPersistent=true}, identity);
Run Code Online (Sandbox Code Playgroud)
这很好用,我可以用以下方法检索这些声明:
private static string GetClaim(string claimType)
{
var identity = (ClaimsPrincipal) Thread.CurrentPrincipal;
var claim = identity.Claims.SingleOrDefault(o => o.Type == claimType);
return claim == null ? null : claim.Value;
}
Run Code Online (Sandbox Code Playgroud)
identity.Claims如预期,该属性包含以下声明:
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: ced2d16c-cb6c-4af0-ad5a-09df14dc8207
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: me@example.com
http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider: ASP.NET Identity
AspNet.Identity.SecurityStamp: 284c648c-9cc7-4321-b0ce-8a347cd5bcbf
http://schemas.microsoft.com/ws/2008/06/identity/claims/role: Admin
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname: My Name
Run Code Online (Sandbox Code Playgroud)
问题是,经过一段时间(通常是几个小时)后,我的自定义声明似乎消失了 - 在此示例中,givenname枚举中不再存在.用户仍然经过身份验证,并且所有默认声明仍然存在.
发生了什么,我该如何解决这个问题?我唯一能想到的是cookie即将到期并在幕后重新发布,但我不知道为什么(或者如果)会发生.
我将声明添加到声明主体身份并让用户登录。在后续请求中,添加的声明可在应用程序中任何位置的声明主体中使用,但只能持续 25 分钟。我没有测试过25到30分钟。30 分钟后,声明主体身份仍经过身份验证,但仅包含来自身份数据库的声明。登录时添加的“CookieClaim”丢失。声明主体身份“IsAuthenticated”仍然是 true,并且导航菜单等中的问候语仍然是“Hi emailaddress”。如果我们在20分钟内提出请求也没关系。
我希望只要用户登录,这些声明就可用。
该应用程序使用 OAuth 从多个外部提供商获取用户的访问令牌和其他信息,该信息用于整个应用程序的授权。我选择将声明中的信息放入cookie中,因为它可能会定期更改,并且不适合存储在Identity数据库中。
以下代码来自我用来演示的 asp.net core 2.2 应用程序的支架 LoginModel。它与我的主应用程序不完全相同,但添加了声明,输入“CookieClaim”并使用相同的方法登录。从“IdentityUser user...”开始的四行实际上是我对模板 asp.net core Web 应用程序所做的唯一更改(使用本地用户帐户,在搭建“登录”页面之后)
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
IdentityUser user = await _signInManager.UserManager.FindByEmailAsync(Input.Email);
ClaimsPrincipal currentUser = …Run Code Online (Sandbox Code Playgroud) 我正在使用Identity 2.x身份验证和授权模型实现Asp.NET MVC应用程序.
在LogIn过程中,我添加自定义声明(不会保留在数据库中!),从LogIn中传递的数据派生到Identity,我可以在以后正确访问它们,直到身份重新生成.
[HttpPost]
[AllowAnonymous]
[ValidateHeaderAntiForgeryToken]
[ActionName("LogIn")]
public async Task<JsonResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
return Json(GenericResponseViewModel.Failure(ModelState.GetErrors("Inavlid model", true)));
using (var AppLayer = new ApplicationLayer(new ApplicationDbContext(), System.Web.HttpContext.Current))
{
GenericResponseViewModel LogInResult = AppLayer.Users.ValidateLogInCredential(ref model);
if (!LogInResult.Status)
{
WebApiApplication.ApplicationLogger.ExtWarn((int)Event.ACC_LOGIN_FAILURE, string.Join(", ", LogInResult.Msg));
return Json(LogInResult);
}
ApplicationUser User = (ApplicationUser)LogInResult.ObjResult;
// In case of positive login I reset the failed login attempts count
if (UserManager.SupportsUserLockout && UserManager.GetAccessFailedCount(User.Id) > 0)
UserManager.ResetAccessFailedCount(User.Id);
//// Add profile claims for LogIn
User.Claims.Add(new ApplicationIdentityUserClaim() { ClaimType …Run Code Online (Sandbox Code Playgroud)