23 мая 2017 г., 13:50 отCommunitylightstrike

Есть ли способ сделать оператор сравнения переменной? [Дубликат]

На этот вопрос уже есть ответ:

Возможны ли переменные операторы? 6 ответов

Похожий наpython: сделать переменную равной оператору (+, /, *, -)

У меня есть фрагмент кода, в котором пользователь может выбрать тип сравнения и значение для сравнения. Мне любопытно узнать, есть ли в Javascript какой-либо способ превратить предоставленное пользователем значение сравнения в реальное сравнение, что позволяет мне сделать что-то вроде:

if (user_val user_comparison other_val) {
    do_something();
}

Вместо того, чтобы делать что-то вроде:

if (user_comparison = '<') {
    if (user_val < other_val) {
        do_something();
    }
else if (user_comparison = '<=') {
    if (user_val <= other_val) {
        do_something();
    }
....etc

Обратите внимание, что в случае сопоставления любого сравнения будет выполнен тот же код.

Ответы на вопрос(3)

14 мая 2012 г., 20:27 отSusam Pal

что вы проверяете предоставленные пользователем операнды и операторы должным образом, чтобы убедиться, что они содержат данные, которые вы хотите, вместо другого исполняемого кода javascript, вы можете объединить два операнда с оператором между ними и передать ихeval() чтобы его казнили.

В настоящее время,eval() является Опасно потому что он может выполнять любой код JavaScript. Пользователь может указать исполняемый и, возможно, вредоносный код JavaScript в качестве оператора иeval() оценил бы это. Поэтому, когда вы делаете конкатенацию, вы должны сделать это после проверки того, что операнд безопасен. Чтобы подчеркнуть этот момент, я напишу один из самых важных принципов компьютерной безопасности в больших шрифтах:

Все данные злые, пока не доказано обратное.

Также обратите внимание, чтоeval() вызывает интерпретатор JavaScript для интерпретации, компиляции и исполнения вашего кода. Это медленно. Хотя вы можете не заметить каких-либо заметных проблем с производительностью, если вы просто используетеeval() время от времени вы можете заметить проблемы с производительностью, если звонитеeval() очень часто, скажем, на каждом ключевом событии.

Рассматривая эти недостаткиeval(), вы, возможно, захотите найти более подходящее решение, подобное тому, которое опубликовал Феликс Клинг. Тем не менее, также можно решить эту проблему с помощьюeval() безопасным образом, как показано ниже:

function compare(a, op, b)
{
  // Check that we have two numbers and an operator fed as a string.
  if (typeof a != 'number' || typeof b != 'number' || typeof op != 'string')
    return

  // Make sure that the string doesn't contain any executable code by checking
  // it against a whitelist of allowed comparison operators.
  if (['<', '>', '<=', '>=', '==', '!='].indexOf(op) == -1)
    return

  // If we have reached here, we are sure that a and b are two integers and
  // op contains a valid comparison operator. It is now safe to concatenate
  // them and make a JavaScript executable code.
  if (eval(a + op + b))
    doSomething();
}

Обратите внимание, что проверка ввода по белому списку почти всегда является лучшей идеей, чем проверка по черному списку. Видетьhttps: //www.owasp.org/index.php/Input_Validation_Cheat_Sheet#White_List_Input_Validatio для краткого обсуждения.

Вот демонстрация этого решения:http: //jsfiddle.net/YrQ4C (Код также воспроизведен ниже):

function doSomething()
{
  alert('done something!')
}

function compare(a, op, b)
{
  if (typeof a != 'number' || typeof b != 'number' || typeof op != 'string')
    return

  if (['<', '>', '<=', '>=', '==', '!='].indexOf(op) == -1)
    return

  if (eval(a + op + b))
    doSomething();
}

// Positive test cases
compare(2, '<', 3)
compare(2, '<=', 3)

// Negative test cases
compare(2, '>', 3)
compare(2, '>=', 3)

// Attack tests
compare('alert(', '"attack!"', ')')

// Edit: Adding a new attack test case given by Jesse
// in the comments below. This function prevents this
// attack successfully because the whitelist validation
// for the second argument would fail.
compare(1, ';console.log("executed code");2==', 2)

Ред .: Демо с включенным тестовым примером Джесси:http: //jsfiddle.net/99eP2

14 мая 2012 г., 20:29 отCommunity

это невозможно. Но вы можете структурировать свой код лучше. Например, у вас может быть таблица поиска:

var operator_table = {
    '>': function(a, b) { return a > b; },
    '<': function(a, b) { return a < b; }
    // ...
};

и позже

if(operator_table[user_comparison](user_val, other_val)) {
    // do something
}

Конечно, вы должны также обработать случай, когдаuser_comparison не существует в таблице.

Это также дает вам лучший контроль над разрешенными и недопустимыми операторами.

Вот DEMO создать к@ Джесси.

14 мая 2012 г., 20:37 отEsen

С @ Susam Pal код не работает. Выкладываю рабочую версию

<html>
  <head>
   <script>
       function CompareSomething(val1, compareString, val2) {  
           eval('if(' + val1 + ' ' + compareString + ' ' + val2 + '){conditionPassed();}else{conditionFailed();}'); 
  }
  function compare(a, op, b) { 
      if (eval(a + op + b))
          conditionPassed();
      else
         conditionFailed();
  }
  function conditionPassed() {
      alert('condition passed');
  }
  function conditionFailed() {
      alert('condition failed');
  }
    </script>
  </head> 
<body>
a:<input id='txt1' type="text" />&nbsp;op:<input id='txt2' type="text" />&nbsp;b:<input id='txt3' type="text" /><br/>
<button id='compare'  onclick='CompareSomething(document.getElementById("txt1").value,document.getElementById("txt2").value,document.getElementById("txt3").value)'>Compare Esen Method</button><br/>
<button id='compare'  onclick='Compare(document.getElementById("txt1").value,document.getElementById("txt2").value,document.getElementById("txt3").value)'>Compare Susam Method</button>
  </body>
 </html>

ВАШ ОТВЕТ НА ВОПРОС