Каков лучший подход для использования Перечисления как одиночный элемент в Java?

Как вы можете видеть, люди предлагают вам максимально использовать подготовленные заявления. Это не так, но когда ваш запрос выполняется всего один раз за процесс, будет небольшое снижение производительности.

Я столкнулся с этой проблемой, но я думаю, что решил ее в очень сложном пути - как хакеры используют, чтобы избежать использования кавычек. Я использовал это в сочетании с эмулированными подготовленными заявлениями. Я использую его, чтобы предотвратить все возможные типы инъекций SQL.

Мой подход:

  • Если вы ожидаете, что ввод будет целым, убедитесь, что он действительно целое число. В языке с переменным типом, таком как PHP, этот очень важен. Вы можете использовать, к примеру, это очень простое, но мощное решение: sprintf("SELECT 1,2,3 FROM table WHERE 4 = %u", $input);
  • Если вы ожидаете чего-то еще от целого шестнадцатеричного значения. Если вы отбросите его, вы полностью избежите ввода. В C / C ++ есть функция, называемая mysql_hex_string() , в PHP вы можете использовать bin2hex() . Не беспокойтесь о том, что экранированная строка будет иметь размер в 2 раза по сравнению с исходной длиной, потому что даже если вы используете mysql_real_escape_string, PHP должен выделять одну и ту же емкость ((2*input_length)+1), что то же самое.
  • hex метод часто используется при передаче двоичных данных, но я не вижу причин, почему бы не использовать его во всех данных для предотвращения атак SQL-инъекций. Обратите внимание, что вам необходимо предварительно добавить данные с помощью 0x или использовать функцию MySQL UNHEX.

Так, например, запрос:

SELECT password FROM users WHERE name = 'root'

Будет:

SELECT password FROM users WHERE name = 0x726f6f74

или

SELECT password FROM users WHERE name = UNHEX('726f6f74')

Hex - идеальный выход.

Разница между функцией UNHEX и префиксом 0x

В комментариях было некоторое обсуждение, поэтому я, наконец, хочу дать понять. Эти два подхода очень похожи, но в некоторых отношениях они немного различаются:

Префикс ** 0x ** может использоваться только для столбцов данных, таких как char, varchar, text, block, binary, и т. д. Кроме того, его использование немного сложно, если вы собираетесь вставить пустую строку. Вам придется полностью заменить его на '', или вы получите сообщение об ошибке.

UNHEX () работает в любом столбце; вам не нужно беспокоиться о пустой строке.


Hex-методы часто используются в качестве атак

Обратите внимание, что этот шестиугольный метод часто используется как атака SQL-инъекции, где целые числа точно так же, как и строки mysql_real_escape_string. Тогда вы можете избежать использования кавычек.

Например, если вы просто делаете что-то вроде этого:

"SELECT title FROM article WHERE id = " . mysql_real_escape_string($_GET["id"])

атака может очень легко ввести вас . Рассмотрим следующий введенный код, возвращенный из вашего скрипта:

SELECT ... WHERE id = -1 union all select table_name from information_schema.tables

и теперь просто извлеките структуру таблицы:

SELECT ... WHERE id = -1 union all select column_name from information_schema.column где table_name = 0x61727469636c65

И тогда просто выберите нужные данные. Разве это не круто?

Но если кодер инъекционного сайта будет шестнадцатеричным, инъекция не будет возможна, потому что запрос будет выглядеть следующим образом: SELECT ... WHERE id = UNHEX('2d312075...3635')

85
задан Community 23 May 2017 в 12:03
поделиться

4 ответа

Предположим, что Вы связываете с чем-то, что будет использовать свойства любого объекта, который это дало - можно передать Elvis. ЭКЗЕМПЛЯР очень легко, но Вы не можете передать Elvis.class и ожидать, что он найдет свойство (если это сознательно не кодируется для нахождения статических свойств классов).

В основном Вы только используете шаблон "одиночка", когда Вы хотите экземпляр. Если статические методы работают хорошо на Вас, то просто используют тех и не беспокоятся перечислением.

95
ответ дан Jon Skeet 24 November 2019 в 08:16
поделиться

Большое преимущество состоит в том, когда Ваш одиночный элемент должен реализовывать интерфейс. Следование Вашему примеру:

public enum Elvis implements HasAge {
    INSTANCE;
    private int age;

    @Override
    public int getAge() {
        return age;
    }
}

С:

public interface HasAge {
    public int getAge();
}

Это не может быть сделано с помехами...

68
ответ дан Nicolas 24 November 2019 в 08:16
поделиться

Одиночные элементы (С сохранением информации) обычно используются, чтобы симулировать не использовать статические переменные. Если Вы не будете на самом деле использовать публично статическую переменную тогда, то Вы одурачите меньше людей.

9
ответ дан Tom Hawtin - tackline 24 November 2019 в 08:16
поделиться

Я бы выбрал самый простой и понятный вариант. Это несколько субъективно, но если вы не знаете, что является наиболее четким, выберите самый короткий вариант.

8
ответ дан 24 November 2019 в 08:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: