是否仅使用eval()来获取来自服务器端安全的数据? (如果没有,请替代)

时间:2011-07-17 23:03:38

标签: javascript html ajax security

我正在创建一个网站,在我加载静态容器页面后,我正在执行ajax请求以加载一些动态内容。基本上,我需要从服务器传递一个整数数组到页面,我正在使用jQuery来加载数据。我在具有已知名称的标签内写入int,并使用eval从中读取数据。这是一个示例标记(从ajax返回):

<span runat="server" class="hidden" id="PhotoList" /> 使用codebehind list.ForEach(p => { sb.Append(p.ID.ToString() + ","); } );,其中sb是一个StringBuilder,因此服务器作为结果返回如下内容:

<span runat="server" class="hidden" id="PhotoList">1,4,5,42,9</span>

我在javascript中声明了变量photoList,我调用了var scriptToEval = "photoList = [" + $("#PhotoList").html() + "];";

eval(scriptToEval);

我不是Javascript的主人,我只是想确保这是安全的,因为有很多关于eval是否安全的讨论。我认为这是安全的(我粘贴的是我使用eval的所有代码),但我可能错过了一点,所以专业人士的意见对我很重要。我知道为什么他们说eval是危险的,因为它能够解释任何恶意与否的代码,但在这里,我认为这种方式根本无法妥协,因为来自服务器的响应完全在我的控制之下。另一种选择是对变量进行另一个ajax调用并直接加载它们而不从返回的数组中获取ajax,但是它会总结为两个调用,(我已经进行了加载调用,因为它确实从服务器加载了一些HTML内容)但是这样,即使有点hacky(将变量放入隐藏的HTML标记),看起来也很方便(毕竟ASP.NET也是为viewstate做的!)。

无论如何,我的重点是eval,这是非常安全的,还是应该考虑一些安全性? Javascript专家请。

5 个答案:

答案 0 :(得分:5)

如果您确定数据是安全的,那么eval()就足够了。

如果您不确定,可以使用JSON.parse()来处理它:

var arr = JSON.parse( "[" + $("#PhotoList").html() + "]" );

对于不支持JSON的浏览器,您可以添加json2库。


另一种可能性是对项目进行split()循环,将它们转换为字符串中的数字。

var arr = $("#PhotoList").html().split(',');

for( var i = 0, len = arr.length; i < len; i++ ) {
    arr[i] = parseInt( arr[i], 10 );
}

编辑:由于您使用的是jQuery,如果由于某种原因您真的不想.eval(),请使用jQuery.parseJSON()[docs]方法。

var arr = jQuery.parseJSON("[" + $("#PhotoList").html() + "]");

编辑2:另一种方法是使用.replace(),将函数作为替换值传递。这将为您处理迭代。

var arr = [];

$("#PhotoList").html().replace(/\d+/g, function( s ) { arr.push( parseInt(s,10) ); });

......有很多方法可以做到。

答案 1 :(得分:2)

当然不安全。使用调试器停止代码并更改元素的内容或脚本使用的变量非常容易。

您需要考虑的是您使用数据的内容。如果有人更改了数据,是否可以使用它来访问不可用的内容,还是可以用它来破坏服务器上的任何数据?

如果更改数据只影响页面上显示的内容,那么数据可以更改不是问题。

答案 2 :(得分:1)

安全,是的,假设您的服务器是安全的。通常,您希望真正避免使用eval()的唯一时间是用户能够添加其他用户可以看到的代码。就像你在展示论坛帖子等时从未想过使用eval()一样。如果代码来自你的服务器,或者用户的输入只是显示给他/她自己,{{1}很好。这基本上是jsfiddle所做的。

答案 3 :(得分:0)

代码

var result = eval(code);

可能会随

而改变
var result = new Function('return '+code+');

答案 4 :(得分:0)

虽然可以在这种情况下使用eval,但我仍然不推荐它,因为它可以产生许多微妙的错误和性能问题。 几乎从不使用eval是一个好主意!

此外,您可以在没有eval的情况下做您想做的事情:

1 - 要设置全局变量,可以使用全局范围对象,而不是使用eval。如果myList是全局变量,则以下所有内容都是等效的:

myList = [1,2,3];
window.myList = [1,2,3];
window['myList'] = [1,2,3];

2 - 为了获得数组元素,您可以使用字符串中的.split()方法:

node.innerHTML.split(',')

3 - 如果您想将字符串转换为第一种简单方法,请使用一元+运算符:

+"3" // is the number 3