Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何保护Web API不被数据检索而不是资源所有者检索_C#_Asp.net Web Api_Asp.net Web Api2_Service Layer - Fatal编程技术网

C# 如何保护Web API不被数据检索而不是资源所有者检索

C# 如何保护Web API不被数据检索而不是资源所有者检索,c#,asp.net-web-api,asp.net-web-api2,service-layer,C#,Asp.net Web Api,Asp.net Web Api2,Service Layer,我有一个asp.NETWebAPI 我想稍后在azure网站上拥有selfhost Web API 登录用户可以在浏览器中执行此操作/api/bankaccounts/3 要获取有关银行账号3的所有详细信息 但登录用户不是银行账号3的所有者 我必须如何设计我的控制器和服务器背后的服务 在中,用户只能检索/修改数据库中自己的资源 更新 在我创建了一个 public class UserActionsAuthorizationFilter : AuthorizationFilterAttribute

我有一个asp.NETWebAPI

我想稍后在azure网站上拥有selfhost Web API

登录用户可以在浏览器中执行此操作
/api/bankaccounts/3

要获取有关
银行账号3的所有详细信息

但登录用户不是
银行账号3
的所有者

我必须如何设计我的控制器和服务器背后的服务

在中,用户只能检索/修改数据库中自己的资源

更新

在我创建了一个

public class UserActionsAuthorizationFilter : AuthorizationFilterAttribute
{
   public override void OnAuthorization(HttpActionContext actionContext)
   {
       if (actionContext != null)
       { 
           bool canUserExecuteAction = IsResourceOwner(actionContext);
           // stop propagation  
       }
   }

private bool IsResourceOwner(HttpActionContext actionContext)
        {
            var principal = (ClaimsPrincipal)Thread.CurrentPrincipal; 
            var userIdAuthenticated = Convert.ToInt32(principal.Claims.Single(c => c.Type == ClaimTypes.Sid).Value);

            int targetId = Convert.ToInt32(actionContext.Request.GetRouteData().Values["Id"]);
            var requstScope = actionContext.ControllerContext.Request.GetDependencyScope();
            var service = (ISchoolyearService)requstScope.GetService(typeof(ISchoolyearService));
            bool canUserExecuteAction = service.HasUserPermission(userIdAuthenticated, targetId);
            return canUserExecuteAction;
        }
}
现在的问题是isResuceOwner硬编码到某个服务=>SchoolyearService,从而绑定到SchoolYearSQL表

我需要让IsResourceOwner方法在所有具有字段UserId/UserEmail的sql表中正常工作

问题是——我真的认为没有人这样做——我必须将每个资源所有者检查映射到HasUserPermission方法中的正确Sql表

这个映射应该是什么样子的

检查控制器名称“SchoolyearController”,因此要检查的表是“schoolyear”表?那太可笑了

此自定义属性“UserActionsAuthorizationFilter”将位于每个“数据”控制器上

无论用户触发哪个控制器url来获取数据,在我必须检查他是否是资源所有者之前

我想我无法在一个过滤器内决定这一点

我必须让数据检索/修改通过控制器,并在数据检索完成之前在存储库中进行ResourceOwner内部检查

您对此有何看法:

API

public async Task<IHttpActionResult> Delete(int id)
{
   var result = await service.Delete(id, User.Identity.UserId);
    if (result == 0)
        return NotFound();
    return Ok();
}
公共异步任务删除(int-id)
{
var result=wait service.Delete(id,User.Identity.UserId);
如果(结果==0)
返回NotFound();
返回Ok();
}
回购

    public async Task<int> Delete(int id, int userId)
    {
        var schoolyerToDelete = await context.Schoolyears.SingleOrDefaultAsync(s => s.Id == id && s.UserId == userId); 

// If schoolyearToDelete is null nothing is removed, thus the affected rows are ZERO.
        context.Schoolyears.Remove(schoolyerToDelete);
       return await context.SaveChangesAsync();
    }
公共异步任务删除(int-id,int-userId)
{
var schoolyerToDelete=await context.Schoolyears.SingleOrDefaultAsync(s=>s.Id==Id&&s.UserId==UserId);
//如果schoolyearToDelete为null,则不会删除任何内容,因此受影响的行为零。
context.schoolyers.Remove(schoolyertodelet);
返回wait context.SaveChangesAsync();
}
  • 对于Get方法,对于错误的UserId不会返回任何内容
  • 对于Create方法:没问题,如果登录,每个人都应该能够创建资源
  • 对于Update方法:与Delete方法相同,学年由id和UserId检索

一般说来,我的存储库中的每种方法都应该考虑CRUD操作中的用户ID。< /P>


您认为如何?

请查看以下链接-它包括身份验证(以便您知道谁在请求)和授权(以便您知道他们是否有权查看数据):


添加一些其他细节——在数据库中定义用户授权的列和/或表是非常常见的。也有可能(取决于您的身份验证机制),身份验证提供程序可能会提供“声明”或其他定义用户有权访问的信息。但是,这可能不太安全,因为您确实需要信任此信息的来源,并有办法确保在提交到api之前未被篡改。

这是一个老问题,但对于遇到类似问题的任何人,这里有一个可能的解决方案

添加抽象层
  • 您可以像以前一样使用UserActionsAuthorizationFilter;只需执行以下操作
  • 使您的所有服务接口(如ISchoolyearService)继承定义HasUserPermission的公共接口
  • 在UserActionsAuthorizationFilter中,添加一个字段:“internal IService ServiceProvider”
  • 在UserActionsAuthorizationFilter中,修改IsResourceOwner():

var service=(IService)requstScope.GetService(this.ServiceProvider);
-然后,更改控制器上的所有属性,以指定它们使用哪种类型的iSeries设备
[UserActionsAuthorizationFilter(ServiceProvider=typeof(ISchoolyearService))]
内部学年控制器:控制器{}
这种方法的一个显著缺点是,如果用户通过了
HasUserPermission()
检查,那么您将只允许用户访问资源,因此,通过这种方式,您将无法创建任何应该公开访问的更深层次的URL,如
/api/testresults/3/public


p.S>您是对的,根据控制器名称确定要检查哪个SQL表是荒谬的我同意在存储库中这样做。在每个记录都有所有者的情况下,我通常会这样做,并且只有所有者才允许修改或删除该记录。
因此,每个记录都需要使用外键存储给其所有者。

此外,由于您说过允许单个用户修改其数据,而不是用户组,因此不能通过授权角色分配来处理,为什么投-1票?敢写评论吗?这个问题让我紧张。总的来说,这里的人不是安全专家。既然你在问题中提到了银行账户,我假设这是被访问的高度机密信息。因此,您确实需要正确理解您在这里所做的事情,以及如何确保它以尽可能安全的方式运行。就此提出问题似乎不是实现这一目标的最佳方式。@David您的解释是错误的。银行账户只是一个示例。@Ewan当然我可以从持票人令牌中获得userEmail/UserId声明。我如何检查每个单独/唯一的请求,即
public interface IService {
  HasUserPermission(int32 userIdAuthenticated, int targetId));}

public interface ISchoolyearService : IService {
  /* Include all other methods except for HasUserPermission */
}
var service = (ISchoolyearService)requstScope.GetService(typeof(ISchoolyearService));
var service = (IService)requstScope.GetService(this.ServiceProvider);
- Then, change all the attributes on your Controllers to specify which type of IService they use
[UserActionsAuthorizationFilter(ServiceProvider = typeof(ISchoolyearService))] <br> internal SchoolyearController : Controller { }