【问题标题】:How to access claims from HttpContext in .Net Core?如何从 .Net Core 中的 HttpContext 访问声明?
【发布时间】:2020-04-27 10:24:29
【问题描述】:

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

    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();

它返回 0 个声明。

请帮忙。

【问题讨论】:

  • 什么时候使用这个服务?这是在中间件中吗?确保app.UseAuthentication() 在使用服务之前发生。
  • @Ruard 在服务中使用。也将 services.AddAuthentication 移到服务之上,但结果相同
  • 我的意思是Configure中的订单,例如app.UseMyMiddlewareThatCallsService(); app.UseAuthentication();。应该反过来。
  • 谢谢@Ruard 它有效:)。请将您的消息添加为答案,以便我将其标记为正确。
  • 我很高兴它现在可以工作了。我已经添加了答案。

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


【解决方案1】:

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

Configure 中,您可以将中间件插入管道。插入中间件时,顺序很重要,不像ConfigureServices 中没有。

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

    SignInAsync 创建一个加密的 cookie 并将其添加到当前响应中。如果未指定 AuthenticationScheme,则使用默认方案。

    如果你使用cookie认证,你可以处理CookieAuthenticationEvents.OnSignedIn事件来更新HttpContext.User

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

    【讨论】:

    • 我也尝试了你的方法,但没有调用事件。
    • @Ravi 回答中的事件是您使用 Cookie 身份验证时的示例。您使用的是什么身份验证架构?
    • services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    • @Ravi 出于测试目的,您想在我的回答中添加services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(...) 并尝试await HttpContext.SignInAsync(IdentityConstants.ApplicationScheme, claims);
    • 是的,喜欢这个 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.Events = new CookieAuthenticationEvents { OnSignedIn = async ctx => { await Task.Run(() => { ctx.HttpContext.User = ctx.Principal; }); } }; });
    【解决方案3】:

    终于有工作代码了。

            services.ConfigureApplicationCookie(options =>
            {
                options.Events.OnSignedIn = (context) =>
                {
                    context.HttpContext.User = context.Principal;
                    return Task.CompletedTask;
                };
            });
    

    【讨论】:

      【解决方案4】:
      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);
      }
      

      【讨论】:

        猜你喜欢
        • 2018-09-20
        • 2021-08-06
        • 2017-03-20
        • 1970-01-01
        • 2019-11-17
        • 2019-11-22
        • 2018-05-28
        • 2015-09-23
        相关资源
        最近更新 更多