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

C# 在Web Api、服务层和数据库中检查用户访问的更好方法,c#,asp.net-web-api,restful-architecture,access-control,n-tier-architecture,C#,Asp.net Web Api,Restful Architecture,Access Control,N Tier Architecture,用户被分配到一个或多个部门 用户有一个或多个角色,例如,Read Own角色只能查看他/她的任务。而团队成员角色可以查看和编辑分配给他/她的部门内的其他任务。 具有管理员角色的用户可以查看和编辑系统中的所有任务 由于防止未经授权的访问和性能原因,我们希望将当前登录的用户id一直传递到数据库,以便只能获取他/她有权访问的记录 我们的系统设计是: WebAPI->业务/服务层->存储库->数据库 目前,我们正在以每种方法将用户id从web API传递到服务层,其中会检查用户是否具有角色团队成员(可以

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

用户有一个或多个角色,例如,Read Own角色只能查看他/她的任务。而团队成员角色可以查看和编辑分配给他/她的部门内的其他任务。 具有管理员角色的用户可以查看和编辑系统中的所有任务

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

我们的系统设计是:

WebAPI->业务/服务层->存储库->数据库

目前,我们正在以每种方法将用户id从web API传递到服务层,其中会检查用户是否具有角色团队成员(可以查看/编辑他有权访问的部门内的其他用户任务) 获取他可以访问的所有部门,然后进一步传递到存储库

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

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

有什么想法吗?

有一个安全层(由修饰服务层类的类组成),用于检查用户是否有权提出请求

例如,如果Web API调用的是
。/viewTask/456
,请检查用户是否是管理员、任务所属部门的团队成员,或者是否是他/她自己的任务

如果访问控制检查通过,装饰器类将传递给包装服务层类;如果访问控制检查失败,则引发未经授权的异常

类似于

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;
    }
}
公共接口ICurrentUser
{
int UserId{get;}
}
公共类AspNetCurrentUser:iccurrentuser
{
public int UserId{get{返回HttpContext.Current.User.GetUserId();}
}
公共课服务:IService
{
私有只读ICurrentUser\u currentUser;
公共服务(ICurrentUser当前用户)
{
_currentUser=currentUser;
}
公共对象WorkWithUserId()
{
返回_currentUser.UserId;
}
}

您可以在cookie中传递用户ID和其他相关信息,然后使用一个基本服务来检查用户ID和其他信息。还可以使用属性作为检查呼叫是否被授权的干净方法。例如,上述相关服务方法[ReadOwnRoleRequired]。目前无法给出代码示例,请暂时留下评论。您刚才提到“团队成员角色可以查看和编辑他/她分配到的部门内的其他任务”。那么我猜你必须传递用户id才能获得相关记录!是吗?@NPhillips:谢谢。但是用户团队成员可以访问其部门中其他用户的任务。我们不仅需要检查角色,还需要检查当前用户有权访问的部门,并将此信息一直传递到db,以便仅查询这些部门。@MukeshModhvadiya:确实如此。但是还有更好的方法吗?请随便吧?看看这样的例子会很有趣-你对Github有什么要点吗?@Iffi我很高兴听到这个!)