Как защитить страницы с двойной аутентификацией: пароль + электронная почта (в настраиваемом поле)

8

Я хотел бы расширить защиту паролем сообщений WordPress, добавив дополнительное поле ввода для электронной почты пользователя.

Таким образом, чтобы увидеть контент, пользователь должен знать пароль и ранее предоставленный адрес электронной почты, который хранится в настраиваемом мета-поле защищенной записи.

Я пытался найти хороший хук, проверяющий это дополнительное поле, но безуспешно. Не могли бы вы дать мне несколько идей, как это сделать? Я не хочу создавать учетные записи пользователей для такого рода функций.

Кровать
источник

Ответы:

7

Когда вы устанавливаете сообщение как защищенное паролем, защита включается по get_the_content()функции. Там WordPress проверяет наличие cookie-файла с почтовым паролем, и, если он не установлен, недействителен или истек срок действия, тогда отображается форма пароля.

Эта форма пароля отправляется туда wp-login.php, где файл cookie устанавливается в соответствии с паролем, записанным в форме, затем запрос снова перенаправляется на почту.

Процесс можно описать так:

  1. перейти на страницу поста
  2. вызовите the_content ()
  3. проверить печенье
  4. если не действителен показать форму пароля
  5. отправить форму на wp_login.php
  6. wp_login.php
  7. установить cookie на основе отправленного pwd и перенаправить на страницу публикации
  8. начать снова форма № 1

Что мы можем сделать:

  • в пункте № 4 используйте хук 'the_password_form'для редактирования вывода формы, добавив поле для электронного письма и скрытое поле с идентификатором записи (на данный момент мы находимся внутри get_the_contentфункции, поэтому у нас есть доступ к глобальной переменной post)
  • К сожалению, в пункте № 3 мы не можем изменить результат проверки файлов cookie (или, по крайней мере, мы не можем сделать это простым и надежным способом). Но в точке №7 WordPress имеет фильтр-ловушку, позволяющую установить срок действия файла cookie: если мы установим это время на прошлую метку времени, файл cookie не будет установлен (а если он существует, то он будет удален) и проверка не будет выполнена. , Таким образом, мы можем использовать этот хук для проверки электронной почты, отправленной через форму, и, благодаря идентификатору записи в скрытом поле, мы можем сравнить его с электронными письмами в мета, если электронная почта не указана или неверна, мы возвращаем прошлую метку времени.

Первый шаг:

/**
 * Customize the form, adding a field for email and a hidden field with the post id
 */
add_filter( 'the_password_form', function( $output ) {

  unset( $GLOBALS['the_password_form'] );
  global $post;
  $submit = '<input type="submit" name="Submit" value="' . esc_attr__('Submit') . '" /></p>';
  $hidden = '<input type="hidden" name="email_res_postid" value="' . $post->ID . '">';
  $email = '</p><p><label for="email_res">' . __( 'Email:' );
  $email .= '<input name="email_res" id="email_res" type="text" size="20" /></label></p><p>';
  return str_replace( $submit, $hidden . $email . $submit, $output );

}, 0 );

И второе:

/**
 * Set the post password cookie expire time based on the email
 */
add_filter( 'post_password_expires', function( $valid ) {

  $postid = filter_input( INPUT_POST, 'email_res_postid', FILTER_SANITIZE_NUMBER_INT );
  $email = filter_input( INPUT_POST, 'email_res', FILTER_SANITIZE_STRING );
  // a timestamp in the past
  $expired = time() - 10 * DAY_IN_SECONDS;
  if ( empty( $postid ) || ! is_numeric( $postid ) ) {
      // empty or bad post id, return past timestamp
      return $expired;
  }
  if ( empty($email) || ! filter_var($email, FILTER_VALIDATE_EMAIL) ) {
      // empty or bad email id, return past timestamp
      return $expired;
  }
  // get the allowed emails
  $allowed = array_filter( (array)get_post_meta( $postid, 'allow_email' ), function( $e ) {
    if ( filter_var( $e, FILTER_VALIDATE_EMAIL) ) return $e;
  });
  if ( ! empty( $allowed ) ) { // some emails are setted, let's check it
    // if the emails posted is good return the original expire time
    // otherwise  return past timestamp
    return in_array( $email, $allowed ) ? $valid : $expired;
  }
  // no emails are setted, return the original expire time
  return $valid;

}, 0 );

Мы сделали.

Теперь создайте сообщение, сохраните его как защищенный паролем и установите несколько разрешенных писем в настраиваемых полях с помощью ключа 'allow_email'. Там нет ограничений на количество писем, которые вы можете добавить ...


Настройки:

Настраиваемые поля для защиты почты


защита почты с помощью пароля


Результат (TwentyThirteen без дополнительного оформления):

Результат в TwentyThirteen без дополнительного стиля

Gmazzap
источник