在控制器外部使用时,IHttpContextAccessor 包含空 User.Identity

dud*_*lis 1 c# asp.net-core-mvc .net-core asp.net-core

我正在编写一个应用程序 ASP.Net Core (2.2) MVC。我需要根据登录用户的某些声明的值过滤 DbContext 内的一些数据。我注入 IHttpContextAccessor,但是当我尝试访问 HttpContext.User.Identity 时 - 所有属性均为 null,所有声明均为空。

这就是我试图实现连接 IHttpContextAccessor 的方式。我使用这样的标准方法:

public void ConfigureServices(IServiceCollection services){
  services.AddHttpContextAccessor();
...
}
Run Code Online (Sandbox Code Playgroud)

然后我构建一个自定义提供程序来从用户中提取声明:

public class GetClaimsFromUser : IGetClaimsProvider
{
  public string UserId {get; private set;}

  public GetClaimsFromUser(IHttpContextAccessor accessor)
  {
     UserId = accessor.HttpContext?.User.Claims.SingleOrDefault(x => x.Type == ClaimTypes.Name)?.Value;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我还将它注入到ConfigureServices方法中:

public void ConfigureServices(IServiceCollection services){
...
  services.AddScoped<IGetClaimsProvider, GetClaimsFromUser>();
...
}
Run Code Online (Sandbox Code Playgroud)

之后,我将其注入到 ApplicationDbContext 中,并尝试在构造函数中设置私有 _userId 字段:

public class ExpenseManagerDbContext: IdentityDbContext<ApplicationUser>
{
  private string _userId;

  public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IGetClaimsProvider claimsProvider) : base(options)
  {
    _userId = claimsProvider.UserId;
    ...
  }
...
}
Run Code Online (Sandbox Code Playgroud)

而这里却是空的。当我访问控制器内的 HttpContext 时,User.Identity 不为空,一切都很好。但是,当我需要在控制器外部访问它时,它是空的。

谢谢你的帮助!!!

完整的代码可以在这里找到: https: //github.com/dudelis/expense-manager/blob/master/ExpenseManager.DataAccess/Concrete/EntityFramework/ExpenseManagerDbContext.cs

pok*_*oke 5

ExpenseManagerDbContext您正在尝试访问应用程序\xe2\x80\x99s所在的用户IdentityDbContext用户。因此,它本身是身份验证系统的依赖项,并且将在框架执行身份验证时得到解决。

\n\n

所以流程有点像这样:

\n\n
    \n
  1. 请求进来了。
  2. \n
  3. 身份验证中间件运行以对用户进行身份验证。
  4. \n
  5. UserManager解决了ExpenseManagerDbContext
  6. \n
  7. ExpenseManagerDbContext解决了IGetClaimsProvider
  8. \n
  9. GetClaimsProvider解析 HttpContext 并尝试访问 user\xe2\x80\x99s 声明。
  10. \n
  11. 身份验证中间件执行身份验证并设置HttpContext.User结果。
  12. \n
\n\n

如果您查看步骤 5 和 6,您将看到在身份验证中间件能够实际对用户进行身份验证并更新上下文上的用户对象之前访问 HttpContext。由于身份验证中间件始终在请求开始时运行,因此情况始终如此。

\n\n

我建议你重新考虑你的ExpenseManagerDbContext因为它可能应该\xe2\x80\x99t 取决于当前登录的用户。它应该独立于此。如果您的逻辑依赖于用户 ID,那么它可能应该是一个单独的服务。

\n