代码改变世界

防止数据被篡改

2012-03-26 14:22  starlet  阅读(1768)  评论(0)    收藏  举报

当参数类型是可变类型时,应先制作一份私有副本,再进行进一步的验证和处理,尤其是安全性非常重要时。因为参数引用的对象内容也许会在经过验证后被改变。

数据通过参数传递到函数中之后,并不意味着函数就对它拥有绝对的控制权。对于大量的引用类型来说,函数外部的程序仍然能够随意对其进行任何操作。这样一来,就可能会存在安全隐患。例如下面一段示例程序:

public bool SendMeMoney(AccountInfo account, int amount)
{
    if (HasPaid(account.Id) == false)
    {
        SendMoneyTo(account.Id, amount);
        return true;
    }
    else
    {
        return false;
    }
}

程序先检查是否向指定的帐户支付过,如果还未支付,则向这个帐户付钱。在正常情况下,程序在调用HasPaid和SendMoneyTo方法时,使用的account.Id应该是同一个帐户号。但由于account是一个引用类型的参数,整个函数在执行的过程中,外部代码仍然可以篡改它的值。这样一来,别有用心的人可以将一个还未支付过的帐户信息输入,等HasPaid函数执行完毕之后,再将Id替换成自己的帐户,以获取非法的重复支付。

对于这类安全性要求非常高的函数来说,应先为所有的可变参数创建一份副本,然后再进行验证和使用,而不是每次都重新获取源数据,以防非法篡改:

代码示例7-14:在安全性较为敏感时,为可变参数制作一份私有副本
public bool SendMeMoney(AccountInfo account, int amount)
{
    string id = account.Id;
 
    if (HasPaid(id) == false)
    {
        SendMoneyTo(id, amount);
        return true;
    }
    else
    {
        return false;
    }
}

这样可保证验证和实际处理时针对的是同样的数据,外界对account数据的更改不会影响函数局部变量id的值。值得注意的是,尽可能地复制元数据,而不是整个对象。如果一定要复制整个对象或者当某个具体数据项自身也是可变类型时,一定要进行数据克隆,而不只是简单的复制引用。