我的方法是自动限制查询当前认证用户账户所拥有的记录。
我使用一个接口来指示哪些数据记录是与账户相关的。
public interface IAccountOwnedEntity
{
Guid AccountKey { get; set; }
}
同时提供一个接口来注入逻辑,用于确定仓库应该针对哪个账户进行操作。
public interface IAccountResolver
{
Guid ResolveAccount();
}
我今天使用的 IAccountResolver 的实现是基于已认证用户的声明。
public class ClaimsPrincipalAccountResolver : IAccountResolver
{
private readonly HttpContext _httpContext;
public ClaimsPrincipalAccountResolver(IHttpContextAccessor httpContextAccessor)
{
_httpContext = httpContextAccessor.HttpContext;
}
public Guid ResolveAccount()
{
var AccountKeyClaim = _httpContext
?.User
?.Claims
?.FirstOrDefault(c => String.Equals(c.Type, ClaimNames.AccountKey, StringComparison.InvariantCulture));
var validAccoutnKey = Guid.TryParse(AccountKeyClaim?.Value, out var accountKey));
return (validAccoutnKey) ? accountKey : throw new AccountResolutionException();
}
}
然后在仓库内,我将所有返回的记录限制为属于该帐户的记录。
public class SqlRepository<TRecord, TKey>
where TRecord : class, IAccountOwnedEntity
{
private readonly DbContext _dbContext;
private readonly IAccountResolver _accountResolver;
public SqlRepository(DbContext dbContext, IAccountResolver accountResolver)
{
_dbContext = dbContext;
_accountResolver = accountResolver;
}
public async Task<IEnumerable<TRecord>> GetAsync()
{
var accountKey = _accountResolver.ResolveAccount();
return await _dbContext
.Set<TRecord>()
.Where(record => record.AccountKey == accountKey)
.ToListAsync();
}
}
使用这种方法,我无需记住在每个查询中应用我的帐户限制。它会自动发生。