Экранирование пользовательских данных без волшебных кавычек
Вопрос
Я рассматриваю, как правильно экранировать данные, поступающие из внешнего мира, прежде чем они будут использоваться либо для управления приложениями, либо для хранения, либо для логики..что-то в этом роде.
Очевидно, что с учетом того, что директива magic quotes вскоре устарела в php 5.3.0+ и была удалена в php6, это становится более актуальным для всех, кто хочет обновиться и получить доступ к новым функциям языка, сохраняя при этом устаревший код (разве нам это не нравится ..).
Однако одна вещь, которую я не видел, - это много дискуссий о теории / наилучшей практике относительно того, что делать после того, как вы защитили свои данные - например, хранить с косыми чертами или без них?Лично я считаю, что хранение экранированных данных в базе данных - плохой шаг, но желательно услышать обсуждение и прочитать несколько тематических исследований..
Несколько ссылок из руководства по PHP просто для справки:
Руководство по PHP - mysql_real_escape_string
Руководство по PHP - htmlspecialchars
и т.д. и т.п.
Есть какие-нибудь советы?
Решение
Взгляните на подготовленные заявления.Я знаю, что в mysql это работает очень хорошо и является безопасной формой получения данных в вашей базе данных.У него также есть несколько преимуществ в производительности.
http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html
У меня есть еще кое-какие ресурсы, если вам интересно.
Надеюсь, это то, что вы ищете, тс.
Редактировать:
Единственное, что я могу добавить, - это использование фильтров в сочетании с подготовленными операторами.Например, чтобы проверить, является ли значение sting, вы используете FILTER_SANITIZE_STRING , или для электронного письма вы используете FILTER_SANITIZE_EMAIL .
Это экономит некоторое количество кода и работает очень хорошо.Впоследствии вы всегда можете проверить данные своими собственными методами, но есть множество фильтров, которые вы можете использовать.
Другие советы
Используйте правильный метод экранирования данных при выполнении запросов: mysql_real_escape_string, подготовленные запросы и т.д...
Хранить данные в базе данных без изменений
Используйте правильный метод экранирования данных на выходе: htmlspecialchars и т.д..
Для работы с базой данных проверьте параметризованные запросы и подготовленные операторы. PDO и mysqli хороши для этого.
Htmlspecialchars - это правильный инструмент для отображения текста в HTML документы.
И, как вы упомянули php 5.3, у вас есть доступ к функциям фильтра , которые необходимо использовать при обработке пользовательских данных.
Все очень просто.ВСЕ входящие данные должны быть прогнаны mysql_real_escape_string() прежде чем вставить его в базу данных.Если вы знаете, что что-то должно быть, например, целым числом, установите для него значение integer перед вставкой и т.д.Помните, что это делается только для того, чтобы остановить SQL-инъекцию.XSS и проверка данных - это разные вещи.
Если вы хотите, чтобы что-то было электронным письмом, вам, очевидно, необходимо проверить это, прежде чем вставлять в базу данных.
htmlentities() очищает данные, то есть это изменять данные.Я думаю, вам всегда следует хранить необработанные данные в базе данных, и когда вы получите эти данные, выберите, как вы хотите их очистить.
Мне нравится использовать следующую функцию в качестве "оболочки" для mysql_real_escape_string() функция.
function someFunction( $value )
{
if ( is_int( $value ) || is_float( $value ) ) {
return $value;
}
return "'" . mysql_real_escape_string( (string) $value ) . "'";
}
Если значение является числом с плавающей запятой или целым числом, то нет смысла запускать mysql_real_escape_string().Причина, по которой я преобразую значение в строку перед передачей его в mysql_real_escape_string(), это потому, что иногда значение может не быть строкой.
Пример того, что значение не является строкой:
http://localhost/test.php?hello []=тест
Внутри test.php ты бежишь mysql_real_escape_string() в $_GET['hello'] ожидаю, что hello будет строкой.Ну, поскольку пользователь установил значение в массив, это фактически вызовет уведомление, поскольку hello не является строкой.