Должен ли я санировать адрес электронной почты перед передачей его функции is_email ()?


13

Я использую, is_email()чтобы проверить, действителен ли предоставленный пользователем адрес электронной почты. Например:

$email = $_POST['email'];
if ( is_email( $email ) )
    // Do something.

Насколько мне известно, ничто в этой функции не записывает информацию в базу данных. Должен ли я проводить санитарную обработку, $emailпрежде чем передать ее в функцию?


Кайзер, спасибо за редактирование. Это на самом деле санитария для меня, но я уверен, что большинство читателей здесь будут использовать z :)
Генрирайт

Ответы:


5

Если посмотреть на is_email()функциональность trac, похоже, что вам не нужно обрабатывать данные, так как это просто тестирование строк. Я бы даже сказал, что если эта функция возвращает значение true, вам не нужно очищать ее перед отправкой в ​​базу данных.


Мои мысли именно о струнном тестировании. Я думаю, что все еще продезинфицирую перед отправкой в ​​БД, вы, вероятно, правы, что в этом нет необходимости, но я нервничаю, когда дело доходит до этих вещей :)
henrywright

Правда, лучше, чем потом сожалеть, и затраты на санитарию были бы совершенно незаметны.
Howdy_McGee

18

WordPress и PHP ядро

is_email()Функция Source является типичной реализацией WordPress и не полностью работать с тем, что RFC 6531 позволяет. Одной из причин может быть то, что FILTER_VALIDATE_EMAILконстанта PHP по умолчанию для filter_var()не намного лучше при проверке чего-либо в соответствии с руководящими принципами Internet Engineering Task Force (IETF®) .

стандарты

Дело в том, что RFC 6531 допускает «символы Юникода за пределами диапазона ASCII» . А именно это (для локальной части - до @):

  • Прописные и строчные буквы английского алфавита (a – z, A – Z) (ASCII: 65–90, 97–122)
  • Цифры 0в 9(ASCII: 48–57)
  • Эти специальные символы: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Символ .(точка, точка, точка остановки) (ASCII: 46) при условии, что он не является первым или последним символом, а также при условии, что он не появляется последовательно (например John..Doe@example.com, не допускается).
  • Специальные символы допускаются с ограничениями. Они есть:
    • Космос и "(),:;<>@[\](ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)
    • Ограничения для специальных символов заключаются в том, что они должны использоваться только в том случае, если они заключены в кавычки, и что двум из них (обратный слеш \ и кавычка "(ASCII: 92, 34)) также должен предшествовать обратный слеш \(например, "\\"и "\"") ,
  • Комментарии допускаются с круглыми скобками в любом конце локальной части; Например, john.smith(comment)@example.comи (comment)john.smith@example.comоба эквивалентны "john.smith@example.com", но john.(comment)smith@example.comбудут недействительными.
  • Международные символы выше U+007F, закодированные как UTF-8, разрешены RFC 6531, хотя почтовые системы могут ограничивать какие символы использовать при назначении локальных частей.

и для глобальной / доменной части:

Часть имени домена в адресе электронной почты должна соответствовать строгим правилам: она должна соответствовать требованиям к имени хоста, состоящему из букв, цифр, дефисов и точек. Кроме того, доменная часть может быть литералом IP-адреса, заключенным в квадратные скобки, такие как jsmith@[192.168.2.1]или jsmith@[IPv6:2001:db8::1][…]

Источник: Википедия

Что действительно?

Это может привести к странным, но действительным адресам электронной почты, подобным следующему:

  • localpart.ending.with.dot.@example.com
  • (comment)localpart@example.com
  • "this is v@lid!"@example.com
  • "much.more unusual"@example.com
  • postbox@com
  • admin@mailserver1
  • "()<>[]:,;\\@\"\\\\!#$%&\'*+-/=?^_`{}| ~.a"@example.org
  • " "@example.org

Источник: php.net / author gt@kani.hu - пример, исправленный автором этого поста

рамки

Существуют также локальные ограничения и ограничения длины домена:

Формат адресов электронной почты - это local-part@domainкогда локальная часть может иметь длину до 64 символов, а имя домена может содержать не более 253 символов, но максимальная длина 256 символов прямого или обратного пути ограничивает весь адрес электронной почты до быть не более 254 символов . [2] Формальные определения приведены в RFC 5322 (разделы 3.2.3 и 3.4.1) и RFC 5321 - с более читаемой формой, приведенной в информационном RFC 3696 [3] и связанных с ним ошибках. ,

Источник: Википедия

Ограничения WordPress

И вот что проверяет WordPress:

  • Проверить на минимальную длину письма можно: strlen( $email ) < 3
  • Проверить наличие символа @ после первой позиции: strpos( $email, '@', 1 ) === false
  • Тест на недопустимые символы: !preg_match( '/^[a-zA-Z0-9!#$%&\'*+\/=?^_`{|}~\.-]+$/', $local )
  • Тест на последовательности периодов: preg_match( '/\.{2,}/', $domain )
  • Тест для ведущих и конечных периодов и пробелов: trim( $domain, " \t\n\r\0\x0B." ) !== $domain
  • Предположим, что в домене будет как минимум две подпрограммы: $subs = explode( '.', $domain );и затем
    • 2 > count( $subs )
    • trim( $sub, " \t\n\r\0\x0B-" ) !== $sub
    • !preg_match('/^[a-z0-9-]+$/i', $sub )

Источник: WP Core v4.0

Фильтры и пользовательская проверка

Все вышеперечисленные случаи приведут is_email()к возврату false. Результат может фильтроваться (обратный вызов может быть присоединен), и у фильтра будет три аргумента, где последний аргумент является причиной. Пример:

return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );

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

Это позволяет добавлять специальные проверки, например, разрешать использование доменов Umlaut, частей домена только для TLD и т. Д.

Вывод

WordPress безопасен в большинстве случаев, но более ограничен, поскольку почтовые серверы должны соответствовать RFC. Имейте в виду, что не каждый почтовый сервер будет соответствовать рекомендациям RF 6531.

редактировать

Забавный побочный эффект: внутри есть две взаимосвязанные функции ~/wp-includes/formatting: is_email()и sanitize_email(). Они практически одинаковые функции. Я понятия не имею, почему кто-то решил, что было бы неплохо скопировать содержимое функции из одного в другое, вместо того, чтобы просто добавить одно в качестве обратного вызова к фильтрам, которые предоставляет другой. Поскольку v0.71 и v1.5 совпадают, я лично буду использовать позже, когда вы получите очищенную строку. Обратите внимание, что даже говорится, что он не соответствует RFC.is_email() sanitize_email() is_email()


Таким образом, вы говорите, что теоретически будут адреса электронной почты, которые полностью действительны в соответствии с RFC 6531, но WordPress сочтет их недействительными?
Генрирайт

Некоторые да. Например, домены только TLD, домены umlaut и т. Д., Как вы можете прочитать в последнем абзаце перед заключением в ответе. Пожалуйста, прочитайте ответ снова. Я знаю, это много, чтобы обернуть голову вокруг, но оно того стоит.
Кайзер

1
Я на самом деле уже прочитал это дважды, потому что это то, что стоит понять! Спасибо за такой подробный ответ :)
henrywright

2

Дезинфицировать все вещи!

Одно из основных правил безопасности - никогда не доверять вводу пользователя. В общем, я не беспокоюсь о реализации is_email () или любой другой конкретной функции, или если эта функция делает что-то опасное с тем, что я ей даю. Возможно, реализация когда-нибудь изменится. Кто знает. Я должен предположить, что это может быть скомпрометировано. Всегда следует исходить из того, что пользовательский ввод активно враждебен, вдвойне для всего, что в конечном итоге предназначено для базы данных, и для очистки каждого бита пользовательского ввода перед передачей его какой-либо функции. Это просто хорошая, общая гигиена безопасности.


Я думаю, что вы ударили по голове, когда сказали, что никогда не знаете, изменится ли реализация. Это может быть нормально, чтобы не дезинфицировать сейчас, но кто знает, изменится ли это позже?
Генрирайт
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.