成功登录后无法访问当前用户声明

问题描述 投票:0回答:1

我目前正在开发 ASP.NET Core 应用程序,我希望我的应用程序具有多租户功能,因此我添加了一个

TenancyProvider
服务,该服务被注入到我的
DbContext
中(以便我可以设置全局查询过滤器稍后):

public class TenancyProvider : ITenancyProvider
{
    private readonly IHttpContextAccessor _context;

    public TenancyProvider(IHttpContextAccessor context)
    {
        _context = context;
    }

    public string? AuthenticatedUser() => _context.HttpContext?.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
}

我现在的问题是这个方法总是返回null。在调试模式下检查调用时,我发现

ClaimsPrincipal
不包含任何数据,即使在登录后也是如此。总是有 0 个声明,并且
IsAuthenticated
总是 false,所以我猜测 cookie 或从中读取数据存在问题。在 Chrome 开发工具中,我至少可以看到身份 Cookie 的存在。

对于身份验证,我使用

AspNetCore.Identity
。这是我的登录服务的当前代码:

[HttpPost]
public async Task<IActionResult> Login(LoginDTO loginDTO, string? ReturnUrl)
{
    if (ModelState.IsValid == false)
    {
        ViewBag.Errors = ModelState.Values
                                   .SelectMany(x => x.Errors)
                                   .Select(x => x.ErrorMessage);
        return View(loginDTO);
    }

    var user = await _userManager.FindByEmailAsync(loginDTO.Email);

    if (user == null)
    {
        ModelState.AddModelError("Login", "Ungültiger Benutzer");
        return View(loginDTO);
    }

    var result = await _signInManager.PasswordSignInAsync(loginDTO.Email, loginDTO.Password, isPersistent: false, lockoutOnFailure: false);

    if (result.Succeeded)
    {
        //Return URL Redirect
        if (!string.IsNullOrEmpty(ReturnUrl) && Url.IsLocalUrl(ReturnUrl))
        {
            return LocalRedirect(ReturnUrl);
        }

        return RedirectToAction("Index", "Orders");
    }

    ModelState.AddModelError("Login", "Ungültiger Benutzername oder Passwort");
    return View(loginDTO);
}

我也尝试手动添加声明,但这对情况没有帮助,所以我再次将其删除。

这是我的

Program.cs

...
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<ITenancyProvider, TenancyProvider>();

builder.Services.AddDbContext<ApplicationDbContext>(
    options =>
    {
        options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
    });

builder.Services.AddIdentity<ApplicationUser, ApplicationRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders()
    .AddUserStore<UserStore<ApplicationUser, ApplicationRole, ApplicationDbContext, Guid>>()
    .AddRoleStore<RoleStore<ApplicationRole, ApplicationDbContext, Guid>>();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
}
else
{
    app.UseDeveloperExceptionPage();
}

app.UseHsts();
app.UseHttpsRedirection();

Rotativa.AspNetCore.RotativaConfiguration.Setup("wwwroot", wkhtmltopdfRelativePath: "Rotativa");

app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();

//app.MapRazorPages();

app.Run();

如果这只是我在这里遗漏的一件小事,我不会感到惊讶,但我现在已经花了几个小时在网络上搜索并尝试不同的解决方案。

如果您需要更多信息,请告诉我。我真的很期待您的答复。

干杯

更新 这是我在数据库上下文中调用租户提供程序的代码:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
{
    private readonly string _tenantId;

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, ITenancyProvider tenancyProvider) : base(options) 
    {
        _tenantId = tenancyProvider.AuthenticatedUser();
    }
...

这是一个屏幕截图,显示空的

Claims
列表,并且
IsAuthenticated
false
。当我截取屏幕截图时,用户已经登录。

应用程序的行为就像用户已登录一样。我可以访问如果未登录则无法访问的控制器和页面。

asp.net-core asp.net-core-identity claims
1个回答
0
投票

显然,问题是您无法从

HttpContext
构造函数中的
DbContext
访问用户。我在这里找到了一个适合我的用例的解决方案Stackoverflow 讨论。更多详细信息也可以在这个Github问题中找到。

您可以执行以下操作:

您需要延迟获取用户信息,直到您真正需要它们为止。因此,我现在只需将

TenancyProvider
服务注入到我的构造函数中。我还引入了一个保存租户 ID 的属性,并且 getter 称为
TenancyProvider
。基本上就是这样。

我的

DbContext

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, Guid>
{
    private readonly ITenancyProvider _tenancyProvider;

    private ClientID Tenant
    {
        get
        {
            string? tenant = _tenancyProvider.AuthenticatedUser();
            return tenant.IsNullOrEmpty() ? ClientID.CreateEmpty() : new ClientID(Guid.Parse(tenant));
        }
    }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, ITenancyProvider tenancyProvider) : base(options) 
    {
        _tenancyProvider = tenancyProvider;
    }
    //other members
}

我只是在我的

OnModelCreating()

中做
modelBuilder.Entity<Order>()
    .HasQueryFilter(x => x.ClientID == Tenant);
© www.soinside.com 2019 - 2024. All rights reserved.