2011-03-22 58 views
2

我正在做的是創建一個真值表生成器。使用用戶提供的函數(例如a && b || c),我試圖讓JavaScript顯示a,b和c的所有組合以及函數的結果。如何讓用戶安全地輸入JavaScript函數?

問題是我不完全確定如何解析用戶提供的功能。用戶可以基本上把他想要的所有東西放在一個函數中,這可能會改變我的網站的效果。

eval()根本不安全;既不是new Function(),因爲兩者都可以讓用戶把所有的東西放在他喜歡的功能。通常JSON.parse()eval()的一個很好的選擇,但是JSON中不存在函數。

所以我想知道如何將一個像a && b || c這樣的自定義布爾運算符字符串解析爲函數,而忽略任何惡意代碼字符串。函數內只允許布爾運算符(&&, ||, !)。

+0

和你怎麼定義什麼是「惡意代碼」? – 2011-03-22 14:06:04

+1

用戶無法使用瀏覽器控制檯並執行任何他想要的JS?或者我錯過了什麼? – 2011-03-22 14:06:15

+0

嗯 - 這是正確的。然而,我的意思是,我希望能夠看到一個函數是否是布爾運算符('a && b || c')的組合或者它是包含AJAX調用等的東西。 – pimvdb 2011-03-22 14:08:53

回答

1

即使你檢查布爾表達式,我可以這樣做:

(a && b && (function() { ruinYourShit(); return true; })()) 

這是爲了說明你的問題不是在一般情況下可以解決的。

爲了使其適用於您的情況,您必須對變量命名施加嚴格限制,例如要求所有變量都是單個字母表字母,然後使用正則表達式在發現其他任何內容時將其踢回。另外,要「匹配」一個布爾表達式,實際上你必須爲該表達式開發一個語法。你試圖解析一個非常規的語言(javascript),因此你不能寫一個正則表達式來匹配任意複雜度的任何可能的布爾表達式。基本上,你試圖解決的問題真的很難。

假設你不希望未來的世界轟然倒塌,如果有人毀了你的廢話,你可以通過簡單地檢查了function關鍵詞,不允許包含在{}任何邏輯代碼塊開發足夠好的解決方案

+0

好吧,像忽略代碼用'{'是我猜想的一個好開始。感謝你的例子。 – pimvdb 2011-03-22 14:10:33

+0

@pimvdb:我不能告訴你的問題,但如果你的過濾與安全有關,你一定要做* white *列表,而不是* black *列表! – 2011-03-22 14:13:59

1

只要您對任何需要輸入的服務器端腳本都有適當的驗證/過濾器,我就不會看到使用eval()並讓用戶執行任何操作的問題。當然,用戶可以做一些破壞你的頁面的東西,但是他可以做到這一點。用戶可以使用任意數量的內置瀏覽器功能或附加組件輕鬆地在自己的頁面上運行他想要的任何JavaScript(s)。

1

我會做的首先將用戶輸入拆分爲令牌(變量名稱,操作符和可能用於分組的括號),然後從中構建表達式樹,然後從表達式樹生成相關輸出運行一些簡化)。

因此,例如,將字符串「a &!b」分解爲令牌序列「a」「&」「!」 「b」,然後通過並(最終)構建類似於:booland(boolvar(「a」),boolnot(boolvar(「b」))),然後您有一個合適的數據結構來運行您的(自定義,希望注入免費)評估者結束。

+0

這似乎變得相當複雜,但它肯定是一個好方法。 – pimvdb 2011-03-22 14:14:17

+0

不需要太複雜,你可以利用正則表達式來進行標記,並且使用合適的記號類來保持狀態(本質上「我們現在在哪裏,在字符串中」),應該可以做到接近單一傳遞你的字符串進行令牌化,然後使用Dijkstra的Shunting Yard算法來構建表達式樹。用幾次手工編碼類似的東西來獲得更「完整」的數學表達式,它不應該花費幾個小時。或者,查找JavaScript的解析器生成器(我不知道這樣的野獸是否存在)。 – Vatine 2011-03-22 15:18:21

0

我結束了正則表達式:

if(!/^[a-zA-Z\|\&\!\(\)\ ]+$/.test(str)) { 
    throw "The function is not a combination of Boolean operators."; 
    return; 
} 
相關問題