我正在创建一个具有不同角色的用户的Web,此外,作为任何其他应用程序,我不希望用户A访问用户B的资源。如下所示:
订单/1(用户A) 订单/2(用户B)
当然,我可以从请求中获取JWT,并查询数据库以检查该用户是否拥有该订单,但这将使我的控制器操作太重。
这个示例使用AuthorizeAttribute,但它似乎太宽泛了,我将不得不为API中的所有路由添加大量的条件,以检查访问的是哪一条路由,然后查询数据库,进行几个连接,这些连接将导致返回uses表,如果请求是否有效,则返回。
更新 对于路线,第一道防线是一种安全策略,它需要某些要求。 我的问题是关于第二条防线,它负责确保用户只访问他们的数据/资源。
在这种情况下有什么标准的方法要采取吗?
发布于 2020-04-23 20:43:00
我采取的方法是自动将查询限制到当前通过身份验证的用户帐户拥有的记录。
我使用一个接口来指示哪些数据记录是帐户特定的。
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();
}
// Other CRUD operations
}使用这种方法,我不需要记住对每个查询应用我的帐户限制。这只是自动发生的。
发布于 2020-04-23 20:17:40
发布于 2020-04-28 08:54:09
以确保用户A不能使用Id=2查看订单(属于用户B)。我会做两件事中的一件:
One:有一个GetOrderByIdAndUser(long orderId, string username),当然您可以从jwt获取用户名。如果用户不拥有订单,他就不会看到它,也不会有额外的db-调用。
2:首先从数据库中获取Order GetOrderById(long orderId),然后验证该订单的username-属性与jwt中登录的用户相同。如果用户不拥有订单抛出异常,返回404或任何东西,并且没有额外的db-调用。
void ValidateUserOwnsOrder(Order order, string username)
{
if (order.username != username)
{
throw new Exception("Wrong user.");
}
}https://stackoverflow.com/questions/61259702
复制相似问题