如何通过双重身份验证保护页面:密码+电子邮件(在自定义字段中)


8

我想通过为用户电子邮件添加额外的输入字段来扩展帖子的WordPress密码保护。

因此,为了查看内容,用户将必须知道密码和先前给定的电子邮件,该电子邮件存储在受保护帖子的自定义元字段中。

我试图找到一个检查该额外字段的好方法,但是没有成功。您能给我一些如何做的想法吗?我不想为此功能创建用户帐户。

Answers:


7

当您将帖子设置为受密码保护时,该保护即发生在get_the_content()功能上。WordPress会检查发布的密码cookie,如果未设置,则无效或已过期,然后显示密码表格。

将此密码表单提交到wp-login.php,根据该表单中写入的密码设置一个cookie,然后将请求再次重定向到该帖子。

可以这样描述该过程:

  1. 去发布页面
  2. 调用the_content()
  3. 检查cookie
  4. 如果无效,请显示密码表格
  5. 提交表单到wp_login.php
  6. wp_login.php
  7. 根据提交的密码设置cookie,然后重定向到帖子页面
  8. 重新开始表格#1

我们可以做什么:

  • 第4点,使用钩子'the_password_form'编辑表单的输出,添加电子邮件字段和带有帖子ID的隐藏字段(这时我们在get_the_content函数内部,因此我们可以访问全局post变量)
  • 不幸的是,在第3点,我们无法更改Cookie检查的结果(或者至少我们不能以简单可靠的方式)。但是在第7点,WordPress具有允许设置cookie过期的过滤器挂钩:如果我们将该时间设置为过去的时间戳,则将不会设置cookie(如果存在,它将被删除),因此验证将失败。因此,我们可以使用该钩子来检查通过表单提交的电子邮件,并且由于隐藏字段中的帖子ID,我们可以将其与元数据中的电子邮件进行比较,如果未提供或错误的电子邮件,我们将返回过去的时间戳。

第一步:

/**
 * 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'。您可以添加的电子邮件数量没有限制...


设定:

自定义字段以允许电子邮件帖子保护


通过密码进行后期保护


结果(二十三个十三,没有其他样式):

结果为二十三个,没有其他样式

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.