在 Web Api、服务层、数据库中检查用户访问的更好方法

Better approach to check users access in Web Api, Service layer, DB

用户被分配到一个或多个部门。

用户有一个或多个角色,例如,Read Own角色只能查看his/her任务。虽然 团队成员 角色可以查看和编辑部门 he/she 分配给的其他任务。 角色为 Admin 的用户可以查看和编辑系统中的所有任务。

由于防止未经授权的访问和性能原因,我们希望将当前登录的用户 ID 一直传递到数据库,以便只能获取 he/she 有权访问的记录。

我们的系统设计是:

Web API -> Business/Service 层 -> 存储库 -> DB

目前,我们在每个方法中将用户 ID 从 Web API 传递到服务层,例如检查用户是否具有角色 团队成员(谁可以 view/edit 其他用户 他有权访问的部门内的任务) 并获取他有权访问的所有部门,然后将其进一步传递给存储库。

是否有更好的方法来避免在每个方法中传递用户 ID? 上述设计中检查用户访问权限的最佳位置是什么?

理想情况下,我们希望没有用户 ID 参数的方法能够使用相同的 类 在另一个应用程序中进行报告。

有什么想法吗?

有一个安全层(由装饰您的服务层 class 的 class 组成)检查用户是否有权提出请求。

例如,如果您的 Web API 调用是 ../viewTask/456 检查用户是否是管理员,任务所属部门的团队成员,或者它是否是 his/her 自己的任务。

如果访问控制检查通过,则装饰器 class 会向下传递到包装服务层 class,如果失败则引发未授权异常。

类似...

public class SecuredTaskController : ApiController
{
    private IContext _context;
    private ITaskService _taskService;
    // other services needed for access check (eg. userService?)

    public SecuredTaskController(ITaskService taskService, IContext context
        // other services needed for access check (eg. userService?)
        )
    {
        _taskService = taskService;
        _context = context;
    }

    public IHttpActionResult Get(Task task)
    {
        if (hasGetAccess(task, _context.UserId))
            return Ok(_taskService.Get(task));
        else
            return Unauthorized();
    }

    private bool hasGetAccess(Task task, long userId)
    {
        // check if userId has acces to get task
    }
}

使用依赖项注入将一些 ICurrentUser 实例注入需要用户 ID 来执行查询和其他任务的服务。

public interface ICurrentUser
{
    int UserId { get; }
}

public class AspNetCurrentUser : ICurrentUser
{
    public int UserId { get { return HttpContext.Current.User.GetUserId<int>(); } }
}

public class Service : IService
{
    private readonly ICurrentUser _currentUser;

    public Service(ICurrentUser currentUser)
    {
        _currentUser = currentUser;
    }

    public object WorkWithUserId()
    {
        return _currentUser.UserId;
    }
}