【问题标题】:Prevent certain fields from being overwritten with PATCH in .NET Azure Web Api防止某些字段被 .NET Azure Web Api 中的 PATCH 覆盖
【发布时间】:2015-01-19 13:38:27
【问题描述】:

我正在创建一个带有 .NET 后端的 Azure 移动服务,该后端使用 TableController(ApiController 的子类)来处理 REST 请求。

在我的 PATCH 方法中,我想限制允许更新的字段集。我有一个 AccountController,我不希望字段 UsernameUserId 被覆盖。

public class AccountController : TableController<Account>
{
...
// PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
   public Task<Account> PatchAccount(string id, Delta<Account> patch)
   {            
            return UpdateAsync(id, patch);          
   }
...
}

如果连接到 API 的客户端尝试更新用户名或用户 ID,我想发回一个有意义的 HTTP 响应,例如 403: Forbidden 或类似的。所以我需要一些方法来了解 Delta 补丁的内容,或者在更新“禁止”字段时自动响应。

【问题讨论】:

    标签: c# .net azure asp.net-web-api


    【解决方案1】:

    不确定是否有内置方法可以做到这一点。但是,您可以解决此问题。创建新属性,比如NonEditable

    public class NonEditableAttribute: Attribute 
    {
    }
    

    将此属性应用于您不想修补的属性。

    public class Account
    {
       [NonEditable]
       public string UserName {get;set;}
    
       ... other properties
    }
    

    编写一些辅助方法来检查 Delta&lt;T&gt; 上更改的属性是否包含这些不可编辑的属性。

    public bool IsValidDelta<T>(Delta<T> delta) where T: class
    {
       // list of property names that can't be patched
       var nonEditablePropertyNames = from p in typeof(T).GetProperties()
                        let attr = p.GetCustomAttribute(typeof(NonEditableAttribute))
                        where attr != null
                        select p.Name;
       // list of property names that were changed
       var changedPropertyNames = delta.GetChangedPropertyNames();
    
       // check if changedPropertyNames contains any of propertyNames, 
       // if yes return false, if no return true;
    }
    

    现在,在您的 ApiController 中,只需检查 Delta&lt;T&gt; 是否包含已更改的不可编辑的属性

    public class AccountController : TableController<Account>
    {
    ...
    // PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
       public Task<Account> PatchAccount(string id, Delta<Account> patch)
       {    
           if(IsValidDelta(patch))        
                return UpdateAsync(id, patch);          
           else
              // forbidden...
       }
    ...
    }
    

    请注意:代码未经测试,可以更好地设计。这是为了给你一个大致的想法 - 将其视为伪代码。

    【讨论】:

    • 这是伟大的迈克尔!!谢谢!
    • 重点当然是在调用UpdateAsync方法作为响应之前运行你自己的验证逻辑。我通常发现在许多这样的实现中,条件更多是基于授权逻辑或基于被修补资源状态的逻辑,但这是模型定义上数据注释属性的一个很好的使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-12
    • 2018-06-27
    • 2021-02-19
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多