在 ASP.Net Core Identity 中刷新用户 cookie 票证
Posted
技术标签:
【中文标题】在 ASP.Net Core Identity 中刷新用户 cookie 票证【英文标题】:Refresh user cookie ticket in ASP.Net Core Identity 【发布时间】:2017-06-11 17:43:04 【问题描述】:在 ASP.NET Core Web 应用程序的控制器中,我想刷新用户并声明存储在客户端上的 cookie 票证。
客户端经过身份验证和授权,ASP.NET Core Identity 将此信息存储在 cookie 票证中 - 现在在某些控制器操作中,我想刷新 cookie 中的数据。
SignInManager
具有刷新RefreshSignInAsync
的功能,但不接受HttpContext.User
作为参数。
[HttpPost("[action]")]
[Authorize]
public async Task<IActionResult> Validate()
// todo: update the Client Cookie
await _signInManager.RefreshSignInAsync(User); // wrong type
如何刷新 cookie?
【问题讨论】:
好吧,HttpContext.User
包含一个主体(ClaimsPrincipal
,带有身份和声明)。 SignInManager 采用TUser
,这取决于您用于配置身份的用户类型。只需从令牌中获取用户 ID 获取用户并刷新它。可以抽象为动作过滤器或扩展方法,或两者兼而有之
【参考方案1】:
public static class HttpContextExtensions
public static async Task RefreshLoginAsync(this HttpContext context)
if (context.User == null)
return;
// The example uses base class, IdentityUser, yours may be called
// ApplicationUser if you have added any extra fields to the model
var userManager = context.RequestServices
.GetRequiredService<UserManager<IdentityUser>>();
var signInManager = context.RequestServices
.GetRequiredService<SignInManager<IdentityUser>>();
IdentityUser user = await userManager.GetUserAsync(context.User);
if(signInManager.IsSignedIn(context.User))
await signInManager.RefreshSignInAsync(user);
然后在你的控制器中使用它
[HttpPost("[action]")]
[Authorize]
public async Task<IActionResult> Validate()
await HttpContext.RefreshLoginAsync();
或者在动作过滤器中抽象它
public class RefreshLoginAttribute : ActionFilterAttribute
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
await context.HttpContext.RefreshLoginAsync();
await next();
然后在你的控制器中像这样使用它
[HttpPost("[action]")]
[Authorize]
[RefreshLogin] // or simpler [Authorize, RefreshLogin]
public async Task<IActionResult> Validate()
// your normal controller code
【讨论】:
很好——一件事,userManager.GetUserAsync 不返回类型 IdentityUser 而是返回 IdentityRoleEntity,它不能与 RefreshSignInAsync 作为参数一起使用。IdentityRoleEntity
来自哪里?它似乎不是身份的一部分。你的类是从Identity
派生的吗?我问是因为 UserManager 来自 Identity 并且它的通用参数是用户模型,即默认配置中的 UserManager<IdentityUser>
或 UserManager<ApplicationUser>
或任何你命名的类,当你将自己的字段扩展到它时。
啊,是的-我使用了您的示例代码var userManager = context.RequestServices .GetRequiredService<UserManager<IdentityUser>>();
,而没有用我自己的实体类型替换IdentityUser
。我需要改用var userManager = context.RequestServices .GetRequiredService<UserManager<MyIdentityUserType>>();
。
Bisschen mitdenken musst du auch schon ;)
我只是在更改用户角色后使用了扩展方法方法。 cookie 正在正确更新,但视图本身包含错误信息并使用用户的旧角色。我怎样才能做到这一点?【参考方案2】:
如果用户已经注销(他们的访问令牌已过期但他们的刷新令牌仍然有效),这也是可能的。
重要提示:仅当您有“您想记住用户的设备吗?”时,以下内容才有效。在 cognito 配置中设置为“否”。如果有人知道如何使用它,请告诉我。
我们使用以下流程(js 客户端应用程序连接到 .NET Core API):
-
用户使用用户名/密码 (
CognitoSignInManager<CognitoUser>.PasswordSignInAsync
) 登录
客户端收到token
、userID
和refreshToken
并将它们存储在localStorage中。
当原始令牌过期(1 小时)时,客户端会从 API 收到 401 错误。
客户端使用userID
和refreshToken
调用另一个API 端点,然后后者又在我们的用户服务上调用以下代码。
如果刷新结果成功,我们返回新的令牌(AuthenticationResult.IdToken
)。
客户端使用新令牌重复最初在 401 中出错的调用。
这是我们添加到用户服务中的代码:
public async Task<UserLoginResult> SignInRefreshAsync(string uid, string refreshToken)
try
var result = await _cognitoIdentityProvider.InitiateAuthAsync(
new InitiateAuthRequest
AuthFlow = AuthFlowType.REFRESH_TOKEN_AUTH,
ClientId = _pool.ClientID,
AuthParameters = new Dictionary<string, string>
"REFRESH_TOKEN", refreshToken ,
"SECRET_HASH", HmacSHA256(uid + _pool.ClientID, _options.UserPoolClientSecret)
);
if (!result.HttpStatusCode.Successful() || string.IsNullOrEmpty(result.AuthenticationResult?.IdToken))
return new UserLoginResult(UserLoginStatus.Failed);
return new UserLoginResult(UserLoginStatus.Success, uid, null, null, result.AuthenticationResult.IdToken, null);
catch
return new UserLoginResult(UserLoginStatus.Failed);
private static string HmacSHA256(string data, string key)
using (var sha = new System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(key)))
var result = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(data));
return Convert.ToBase64String(result);
IAmazonCognitoIdentityProvider _cognitoIdentityProvider
由 DI 解析。
AWSCognitoClientOptions _options = configuration.GetAWSCognitoClientOptions();
和 IConfiguration configuration
也是从 DI 解析的。
UserLoginResult
是我们持有令牌和刷新令牌的类。显然,相应地进行调整。
请注意,根据您的配置是 Cognito,可能不需要设置 SECRET_HASH
。
【讨论】:
以上是关于在 ASP.Net Core Identity 中刷新用户 cookie 票证的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET CORE 5.0 Identity 显示当前登录用户
Asp.Net core MVC6如何在Identity 3中初始添加角色
如何按照存储库模式在 Asp.Net Core 5.0 项目上实现 .Net Core Identity?