Moz*_*eeb 9 c# asp.net-core-webapi jwt-auth asp.net-core-3.1
我正在创建一个具有不同角色的用户的 Web API,此外,作为任何其他应用程序,我不希望用户 A 访问用户 B 的资源。像下面这样:
订单/1(用户A)
订单/2(用户B)
当然,我可以从请求中获取 JWT 并查询数据库以检查该用户是否拥有该订单,但这会使我的控制器操作变得过于繁重。
此示例使用 AuthorizeAttribute 但它似乎太宽泛了,我必须为 API 中的所有路由添加大量条件以检查正在访问哪个路由,然后查询数据库进行多个连接,返回到用户表以返回如果请求是否有效。
更新
对于路由,第一道防线是需要特定声明的安全策略。
我的问题是关于负责确保用户只能访问他们的数据/资源的第二道防线。
在这种情况下是否有任何标准方法要采取?
小智 4
The approach that I take is to automatically restrict queries to records owned by the currently authenticated user account.
I use an interface to indicate which data records are account specific.
public interface IAccountOwnedEntity
{
Guid AccountKey { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
And provide an interface to inject the logic for identifying which account the repository should be targeting.
public interface IAccountResolver
{
Guid ResolveAccount();
}
Run Code Online (Sandbox Code Playgroud)
The implementation of IAccountResolver I use today is based on the authenticated users claims.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
Then within the repository I limit all returned records to being owned by that account.
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();
}
// Other CRUD operations
}
Run Code Online (Sandbox Code Playgroud)
With this approach, I don't have to remember to apply my account restrictions on each query. It just happens automatically.
| 归档时间: |
|
| 查看次数: |
1929 次 |
| 最近记录: |