在 .net core 2.0 中缓存声明

Caching Claims in .net core 2.0

到处查找,但看起来我现在被卡住了。我在我的应用程序中使用 Windows Active Directory 进行身份验证。 对于授权,我正在使用声明。在有限的 .net 核心文档中搜索后,这就是我的代码的样子。

Startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IPrincipal>(
            provider => provider.GetService<IHttpContextAccessor>().HttpContext.User);
        services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
        services.AddAuthentication(IISDefaults.AuthenticationScheme);

    }

ClaimsTransformer.cs

class ClaimsTransformer : IClaimsTransformation
{
   public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
   {

// call to database to get more claims based on user id ClaimsIdentity.Name
     ((ClaimsIdentity)principal.Identity).AddClaim(new Claim("now",DateTime.Now.ToString()));
     return Task.FromResult(principal);
   }
}

但问题是,每次请求都会调用此代码,并且每次都从数据库加载声明,这是绝对错误的。有什么办法可以缓存它吗?我能够创建一个声明 cookie 并将该 cookie 用于 .net 4.0 中的任何进一步调用。我似乎无法在核心中找到方法。我检查的任何文档都不完整或没有涵盖我的场景。我可以在我的申请中进一步声明文档在此处的说法:https://docs.microsoft.com/en-us/aspnet/core/security/authorization/claims

但是没有提到缓存声明。

有人在同一条船上吗?或者知道出路吗?

我没有做完全相同的事情,但我正在使用 cookie Authentication/Authorization。我学到的大部分内容来自 this microsoft doc,但正如您所说,文档似乎并没有带您一路走来。这是对我有用的:

在startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        ...

        services.AddAuthentication("tanushCookie")
        .AddCookie("tanushCookie", options => {
            options.AccessDeniedPath = "/api/Auth/Forbidden";
            options.LoginPath = "/";
            options.Cookie.Expiration = new TimeSpan(7,0,0,0);
        });
    }


public void Configure(IApplicationBuilder app, 
                      IHostingEnvironment env, 
                      ILoggerFactory loggerFactory)
    {
        ...

        app.UseAuthentication();
    }

然后在处理身份验证的控制器中:

    [HttpPost()]
    [Route("api/[Controller]/[Action]/")]
    public async Task<JsonResult> Login([FromBody]Dictionary<string, string> loginData)
    {
        try
        {
            var loggedIn = true;
            if (loggedIn)
            {
                var claims = new List<Claim> {
                    new Claim(ClaimTypes.Name, "tanush")
                };

                var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
                identity.AddClaims(claims);
                ClaimsPrincipal principal = new ClaimsPrincipal(identity);

                await HttpContext.SignInAsync(
                    "tanushCookie",
                    principal,
                    new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc = DateTime.UtcNow.AddDays(7)
                    });
            }
            return new JsonResult(logRtn);
        }
        catch (Exception ex)
        {
            return new JsonResult(ex.Message);
        }
    }

我不确定您是否可以使用带有 windows 身份验证的 cookie。但是,如果您可以对身份验证请求的结果进行身份验证和分配 loggedIn,则您应该能够在 cookie 中存储某种声明。然后,您可以使用以下命令在可能正在执行 authorization/recalling 值的控制器中调用该声明:

    [HttpGet("[Action]", Name = "GetSomething")]
    [Route("[Action]")]
    public JsonResult something()
    {
        try
        {
            var loggedInUser = HttpContext.User;
            var claym = loggedInUser.Claims.FirstOrDefault(x => x.Type == ClaimTypes.Name);
            if (claym != null)
            {
                return new JsonResult(claym.Value);
                // returns "tanush"
            }
            else
            {
                return new JsonResult("");
            }
        }
        catch (Exception ex)
        {
            return new JsonResult(ex.Message);
        }
    }

您可以在 ClaimsTransformer 构造函数中注入 IMemoryCache 服务。

using Microsoft.Extensions.Caching.Memory;

public class ClaimsTransformer : IClaimsTransformation
{
    private readonly IMemoryCache _cache;

    public ClaimsTransformer(IMemoryCache cache)
    {
        _cache = cache;
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        var cacheKey = principal.FindFirstValue(ClaimTypes.NameIdentifier);

        if (_cache.TryGetValue(cacheKey, out List<Claim> claims)
        {
            ((ClaimsIdentity)principal.Identity).AddClaims(claims);
        }
        else
        {
            claims = new List<Claim>();          

            // call to database to get more claims based on user id ClaimsIdentity.Name

            _cache.Set(cacheKey, claims);
        }

        return principal;
    }
}