【问题标题】:Caching Claims in .net core 2.0在 .net core 2.0 中缓存声明
【发布时间】:2017-09-12 16:34:54
【问题描述】:

四处张望,但看起来我现在被困住了。我在我的应用程序中使用 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

但没有提及缓存声明。

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

【问题讨论】:

  • 我也想知道这个。我将研究@Brad 建议的内存缓存技术。虽然我不喜欢表单身份验证身份缓存在 cookie 中而 Windows 身份验证身份缓存在内存中的不一致。
  • @tanush 一个好问题。我有完全相同的问题 - 我的 TransformAsync 中的数据库调用,以及非常糟糕的官方文档。

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


【解决方案1】:

您可以在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;
    }
}

【讨论】:

  • 这看起来很有希望。我会试试这个,看看效果如何。感谢您提供新的视角。我陷入了 .net 4.0 代码中的整个 cookie 和会话问题。
  • 工作。必须更改其代码才能使其正常工作,但这是可行的解决方案。
  • 您能否提供完整的解决方案以及您更改的代码?我目前正在查看用于 Windows 身份验证的 ClaimsTransformer
  • @mheptinstall 你在问谁?
  • 抱歉应该在我的评论中包含@tanush
【解决方案2】:

我没有做完全相同的事情,但我正在使用 cookie 身份验证/授权。我学到的大部分内容来自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。但是,如果您可以在身份验证请求的结果中进行身份验证和分配登录,您应该能够在 cookie 中存储某种类型的声明。然后,您可以使用以下方法在可能正在执行授权/调用值的控制器中调用该声明:

    [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);
        }
    }

【讨论】:

  • windows 身份验证的问题是它没有任何控制器来处理身份验证。虽然这让我思考,但我可以添加一个用于 Windows 身份验证的中间件,并将声明添加到它们而不是声明转换器中。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2018-08-20
  • 1970-01-01
  • 2019-12-16
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
相关资源
最近更新 更多