Asp.net-MVC自定义验证 - NULL与空

时间:2014-09-03 23:21:47

标签: c# asp.net-mvc validation

为了安全性和一致性,如果字段丢失,我想在回发后进行测试?在Java(特别是servlet)中,当我们执行request.getParameter(key)时,结果是字符串值,否则如果字段丢失则为NULL。在MVC中,我创建了一个自定义验证,我称之为“ThrowOnNull”。我想要捕获的行为是:如果想要的字段丢失(null)我想抛出,否则返回成功。

考虑这个自定义验证器(不起作用):

public class ThrowOnNull: ValidationAttribute
{
   public ThrowOnNull() { }

   protected override ValidationResult IsValid(object value, ValidationContext validationContext)
   {            
       if (value == null)
           throw new Exception(validationContext.MemberName + " field expected, but missing."));            

       return ValidationResult.Success;
   }
}

可以在这里做我想做的事吗?(这个验证器没有按预期工作,这是因为框架将NULL赋给空值[哦亲爱的]。)

更新:根据 @emodendroket ,以下代码示例现在按预期工作:

public class ThrowOnMissing: ValidationAttribute
{
    public ThrowOnMissing() { }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (!HttpContext.Current.Request.Form.AllKeys.Contains(validationContext.MemberName))
            throw new Exception(validationContext.MemberName + " field expected, but missing.");

        return ValidationResult.Success;
    }
}

编辑:我已经清理了问题和示例代码,使其更加清晰,希望它有所帮助。

4 个答案:

答案 0 :(得分:3)

您错过了一个重点 - 当您提交表单时,属于该表单的所有字段都会被提交。如果用户没有填写它们,那么它们就会空白,因此null的验证无法真正起作用......

你应该重新定义什么"缺少价值"装置

编辑:
经过一些讨论后,您似乎并不真正关心空值,而是关注安全性(错误的表单,缺少字段和类似的东西)。在这种情况下,您应该只使用标准 - 防伪令牌,并可能检查请求的来源。你应该比这更好。检查丢失的字段不会有所帮助,因为攻击者也可以轻松地发送这些字段。

  

过度/不足过账是一个真正的问题。此外,如果没有提交字段(由于某种黑客攻击或DOS攻击)

不是真的。

重叠通过控制器上的操作方法处理。它不会接受比您指定的参数更多的参数。

Underposting的处理方式与您没有填写表单中的文本字段的方式相同,如果您已正确验证模型,则再次出现问题。

DDOS攻击无法相信我,如果有人拥有足够强大的网络来导致DDOS,一些检查丢失的字段会有所帮助。只需查看有关攻击的最新案例,您就会明白,如果巨大的服务器无法承受这种情况,您当然无法像这样阻止它。

您的数据验证也不应过于昂贵。它是一个网络,人们不愿意等待太多。

答案 1 :(得分:2)

如果您需要自己的验证器,可以查看字典HttpContext.Current.Request.Form。然后,您可以使用此代码执行您的建议:

if (!HttpContext.Current.Request.Form.AllKeys.Contains("prop"))
  {
    throw new Exception();
  }

答案 2 :(得分:1)

我认为你在这里对事情不合情理。请注意,我说不合理的偏执,因为一点偏执是一件好事。

首先,让我们分析“威胁”并确定风险。你提出了几个论点:

  1. 过帐
  2. 在张贴
  3. 验证空vs null
  4. 如果您使用的是View Model,则第一项不是MVC中的问题。您根本无法发布视图不期望的信息(嗯,您可以,但它被忽略)。如果您没有使用视图模型(或者没有使用正确定义的视图模型),那么您可以使用绑定属性来阻止发布您不想要绑定的项目。

    第二个,欠发布,如果它真的是你的模型的关注(99.999%的时间只是根据需要处理它是非常好的,但好吧,让我们采取你的论点。这里的问题不是验证属性,它是模型绑定器。您只需注册一个自定义模型绑定器,在视图模型中查找缺失值,如果它们为null则抛出。这可以通过反映绑定模型并将其与发布值进行比较,然后抛出

    您的RequiredThrowIfNull方法的问题是..如果它不是必需的并且它已发布,该怎么办?根据你的论点,这仍然是一个错误。

    最后,验证空vs空...你谈论昂贵的验证......我不知道你可以在这里谈论什么样的昂贵验证,但是服务器方面注意到可以考虑的属性昂贵。

    你的属性不起作用的原因是因为框架已经在一个try / catch块中调用了验证属性,如果它是null,那么它就是将它视为空的机制(这种机制也可以像捕获解析一样)类型不正确时的错误,例如日期时间字段中的字符。)

    .NET不是Java,尽管它在很大程度上也是类似的...尝试在.NET中重新实现Java模式会导致你的痛苦,因为许多基本的哲学都是不同的。

    即使我们接受你想要捕获错误或被通知黑客攻击的论点,在大多数情况下投掷也是错误的。相反,只需记录模型绑定器中的信息并继续正常运行。只有当你绝对需要中止请求时才会抛出,并且大部分时间根本就不是这样,即使你被黑了......投掷只会让攻击者改变他们的攻击,直到他们不再获得异常。

    坦率地说,这是一个过度设计,寻找问题的解决方案,并且有许多优秀的.net特定方法来处理您要解决的REAL问题。

答案 3 :(得分:0)

来自 ASP.NET

@ignatandrei 回答了这个问题:

  

默认情况下,MVC将空字符串转换为空字符串。

http://forums.asp.net/t/2006146.aspx?Custom+Validation+and+NULL