我的应用程序的授权是基于"组织"的,用户属于一个组织(像多租户之类的东西?),所以用户将拥有其UserIdOrganizationId.UserId在JWT令牌中提供,但OrganizationId必须根据UserId从数据库获取.

我有一个ICurrentUserService,从HttpContext中减go UserIdOrganizationId:

public class CurrentUserService : ICurrentUserService
{
    public string UserId {get; set;}
    public string OrganizationId {get; set;}

    public CurrentUserService(IHttpContextAccessor httpContextAccessor)
    {
        UserId = httpContextAccessor.HttpContext?.User?.FindFirstValue(nameof(UserId));
        OrganizationId = httpContextAccessor.HttpContext?.User.FindFirstValue(nameof(OrganizationId));
    }
}

DbContext依赖于UserIdOrganizationIdICurrentUserService,它使用OrganizationId作为全局查询过滤器:

public class DbContext
{
    DbContext(ICurrentUserService _currentUserService)
    {
        _organizationId = _currentUserService.OrganizationId;
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        // use OrganizationId for query filter
        builder.Entity<Device>().HasQueryFilter(x => x.OrganizationId == _organizationId);
    }
}

由于我在JWT标记中没有OrganizationId,所以我有一个PermissionsMiddleware来查询OrganizationId,然后将它作为ClaimsIdentity添加到HttpContext‘S ClaimsPrincipal中:

public class PermissionsMiddleware(RequestDelegate next)
{
    public async Task InvokeAsync(HttpContext context, DbContext db)
    {
        string uId = context.User.FindFirst("UserId")?.Value;
        MyUser user = await db.Set<MyUser>().FindAsync(uId);
        string orgId = user.OrganizationId;
        var accountClaims = new List<Claim>()
                                {
                                    new Claim("OrganizationId", orgId)
                                }
        var orgIdentity = new ClaimsIdentity("OrganizationPermission", "name", "role");
        orgIdentity.AddClaims(claimPermissions);

        context.User.AddIdentity(orgIdentity);
    }
}

正如你可能看到的,PermissionsMiddleware取决于DbContext,而DbContext取决于ICurrentUserService,而ICurrentUserService又取决于PermissionsMiddleware提供OrganizationId

当一个请求进来时,一个PermissionsMiddleware被调用,这需要DbContext.所以DbContextPermissionsMiddleware之前启动,而不知道OrganizationId,因为DbContext是一个作用域依赖,它将保持这种方式.

我如何解决这个问题?我可以考虑将DbContextICurrentUserService转换为瞬时依赖项,但这可能会影响性能.

推荐答案

您可以简单地设置一个不依赖于DbContext Id的不同DbContext.当您在单个DbContext中有太多的关注点时,推荐使用这种方法.

public class DbContextMiddleware
{
   // ...
}

然后更改中间件中的依赖关系.

public class PermissionsMiddleware(RequestDelegate next)
{
    public async Task InvokeAsync(
    HttpContext context, DbContextMiddleware db)
   {
       // ..
   }
}

Csharp相关问答推荐

ß != ss与ICU进行不区分大小写的比较

为什么在GuardationRule的收件箱函数中,decode.TryParse(valueString,out valueParsed)在给出1.0.1时返回true?

Unity如何在PlayerPrefs中保存数据?

始终保留数组中的最后N个值,丢弃最老的

MudBlazor—MudDataGrid—默认过滤器定义不允许用户修改基本过滤器

碰撞检测与盒碰撞器,其isTrigger on问题

当通过Google的Gmail Api发送邮件时,签名会产生dkim = neutral(正文散列未验证)'

查找表中的模式

内部接口和类的DI解析

如何从ASP.NET核心MVC视图和Blazor传递数据

C#带主体的主构造函数?

NET8 Maui&;iOS:AppCenter崩溃错误

当我没有此令牌时,为什么语法报告EOF错误?

当我将`ConcurentDictionary`转换为`IDictionary`时,出现了奇怪的并发行为

CRL已过期,但ChainStatus告诉我RevocationStatus未知

正在从最小API-InvocationConext.Arguments中检索参数的FromBodyAttribute

在ObservableCollection上使用[NotifyPropertyChangedFor()]源代码生成器不会更新UI

如何在.NET MAUI上在iOS和Mac之间共享代码?(no条件编译和无代码重复)

将列表转换为带有逗号分隔字符串形式的值的字典

如何获取我在SQL中输入的值