如何从 .Net Core 中的 HttpContext 访问声明?

How to access claims from HttpContext in .Net Core?

使用下面的代码登录自定义声明,它工作正常。

    private async Task SignInAsync(ApplicationUser user)
    {
        var claims = await _claimsPrincipalFactory.CreateAsync(user);

        claims.Identities.First().AddClaims(new[]
        {
            new Claim("xxx", "111"),
            new Claim("yyy", "222")
        });

        await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, claims);
    }

但是当尝试在如下服务中使用 HttpContext 进行访问时

var claims = HttpContext.User.Identities.FirstOrDefault().Claims.ToList();

它 returns 0 个声明。

请帮忙。

这取决于架构的实现,默认情况下身份验证处理程序可能不会更新 HttpContext.User

例如,cookie 身份验证处理程序不会让当前用户登录,而是 only generates authentication ticket and sets it to response

SignInAsync creates an encrypted cookie and adds it to the current response. If AuthenticationScheme isn't specified, the default scheme is used.

如果您正在使用 cookie 身份验证,您可以处理 CookieAuthenticationEvents.OnSignedIn 事件来更新 HttpContext.User:

.AddCookie(IdentityConstants.ApplicationScheme,
    opt =>
    {
        opt.Events = new CookieAuthenticationEvents
        {
            OnSignedIn = async ctx =>
            {
                ctx.HttpContext.User = ctx.Principal;
            }
        };
    });

我的假设是,由于构建管道的语句的顺序,声明丢失了。

Configure 中,您可以将中间件插入管道。插入中间件时,顺序很重要,这与 ConfigureServices 不同。

因此,当在用户通过身份验证之前使用声明的中间件中使用服务时,声明尚不可用,例如:

app.UseMyMiddlewareThatCallsService(); 
app.UseAuthentication();

但是当顺序改变时,索赔是。

app.UseAuthentication();
app.UseMyMiddlewareThatCallsService(); 

终于有了工作代码。

        services.ConfigureApplicationCookie(options =>
        {
            options.Events.OnSignedIn = (context) =>
            {
                context.HttpContext.User = context.Principal;
                return Task.CompletedTask;
            };
        });
if (access token in header or query parameter)
{
    // Set the claims like in the Account/Login action from the interactive login form
    var claims = ...;
    // Local helper method, is used in other places, too
    var claimsIdentity = await SignInAsync(httpContext, claims, false);
    // Set user for the current request
    // This works in that it's in User.Identity, but the auth events won't fire
    httpContext.User = new ClaimsPrincipal(claimsIdentity);
}