无需在每个请求上调用GetUserAsync即可获取用户数据

时间:2018-02-12 12:31:29

标签: c# asp.net-core asp.net-identity

我们目前在AspnetUsers表中存储ClientId。我们使用它来识别客户端登录的用户,以及用于过滤此客户端的数据。

是否有更有效的方法来获取当前用户clientId,在每个控制器中不调用:await _manager.GetUserAsync(_httpContextAccessor.HttpContext.User);在每个Controller中获取clientId?我们可以使用Singleton服务在登录时设置此属性,并将其注入我们的控制器吗?

谢谢,

1 个答案:

答案 0 :(得分:4)

最好的解决方案是将clientid存储为声明,因此当用户登录时,它将被序列化到claimprincipal并包含在auth cookie中。

您可以从默认的Identity ClaimsPrincipalFactory继承并覆盖CreateAsync方法,调用基类来创建然后添加自定义声明。然后你注入你的自定义工厂,它将被使用。然后,您可以从User.Claims获取clientid,其中User是ClaimsPrincipal并且在控制器操作中可用。

通过执行此操作,您只需在登录时点击数据库即可将clientid添加为声明。之后,您可以在用户声明的每个请求上获得它,而无需点击数据库。

我在我的cloudscribe项目中有一个示例,您可以看到我的自定义ClaimsPrincipalFactory

示例代码:

public override async Task<ClaimsPrincipal> CreateAsync(TUser user)
{
    if (user == null)
    {
        throw new ArgumentNullException("user");
    }

    // base class takes care of all the default stuff like roles name id etc
    var principal = await base.CreateAsync(user);

    if (principal.Identity is ClaimsIdentity)
    {
        var identity = (ClaimsIdentity)principal.Identity;
        // add logic to get the clientid
        var clientId = yourmethod();
        var clientIdClaim = new Claim("ClientId", clientId);
        identity.AddClaim(clientIdClaim);

}

}

然后,您可以制作一个扩展方法,以便轻松获取客户端ID声明

public static string GetClientId(this ClaimsPrincipal principal)
{
    if (principal == null)
    {
        throw new ArgumentNullException(nameof(principal));
    }
    var claim = principal.FindFirst("ClientId");
    return claim != null ? claim.Value : null;
}

然后在控制器中你可以使用var cleintId = User.GetClientId();