我的应用程序的授权是基于"组织"的,用户属于一个组织(像多租户之类的东西?),所以用户将拥有其UserId
和OrganizationId
.UserId
在JWT令牌中提供,但OrganizationId
必须根据UserId
从数据库获取.
我有一个ICurrentUserService
,从HttpContext
中减go UserId
和OrganizationId
:
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
依赖于UserId
和OrganizationId
的ICurrentUserService
,它使用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
.所以DbContext
在PermissionsMiddleware
之前启动,而不知道OrganizationId
,因为DbContext
是一个作用域依赖,它将保持这种方式.
我如何解决这个问题?我可以考虑将DbContext
和ICurrentUserService
转换为瞬时依赖项,但这可能会影响性能.