wordpress文章部分内容加密功能的实现方法

搞 WordPress 的都知道:后台「可见性」里只有「公开」和「密码保护」两个按钮。
可我就想问:能不能只加密其中一段?
比如把微信号、服务器 IP、未公开的草稿链接藏起来,其余内容正常阅读。

答案在短代码里。那些「关注公众号获取密码」的增长黑客玩法,内核全是它。但我只想要个干净的「部分加密」,不想整关注、不想存 Session、不想写后台设置页。这个放在以前估计会难道一批人,但是現在AI技术的成熟,催生了新的路径:vibe codding
直接自然语言和 AI提需求:「帮我写个短代码,内容加密、Cookie 记录解锁状态、前端输入框自动聚焦」,复制进 functions.php,三分钟上线。

/**

  • 密码保护短代码

⚠️ 错误:请设置 password 属性

*/
if ( ! function_exists( 'password_lock_shortcode' ) ) {

define( 'PWD_LOCK_MAX_ATTEMPTS', 5 );
define( 'PWD_LOCK_LOCKOUT_SECONDS', 900 );
define( 'PWD_LOCK_COOKIE_TTL', DAY_IN_SECONDS );

function password_lock_shortcode( $atts, $content = null ) {

 $atts = shortcode_atts( [
     'password' => '',
     'id'       => '',
     'hint'     => '',
 ], $atts, 'pwd_lock' );

 $password = $atts['password'];
 $hint     = sanitize_text_field( $atts['hint'] );

 if ( empty( $password ) ) {
     return '<div class="pwd-error">⚠️ 错误:请设置 password 属性</div>';
 }

 // 生成唯一 ID
 $lock_id    = ! empty( $atts['id'] )
     ? sanitize_key( $atts['id'] )
     : 'lock_' . substr( md5( $content . $password . AUTH_SALT ), 0, 12 );

 $cookie_key  = 'pwdlocks_' . md5( $lock_id );
 $post_key    = 'pwd_input_' . $lock_id;
 $nonce_key   = '_wpnonce_pwd_' . $lock_id;
 $attempt_key = 'pwd_attempts_' . md5( $lock_id . ( $_SERVER['REMOTE_ADDR'] ?? '' ) );

 $is_error    = false;
 $is_locked_out = false;

 if ( ! empty( $_POST[ $post_key ] ) && isset( $_POST[ $nonce_key ] ) ) {
     $attempts = (int) get_transient( $attempt_key );
     if ( $attempts >= PWD_LOCK_MAX_ATTEMPTS ) {
         $is_locked_out = true;
     } elseif ( wp_verify_nonce( $_POST[ $nonce_key ], 'pwd_lock_action_' . $lock_id ) ) {

         $input = sanitize_text_field( wp_unslash( $_POST[ $post_key ] ) );

         if ( hash_equals( $password, $input ) ) {
             $hashed = password_hash( $password, PASSWORD_BCRYPT, [ 'cost' => 10 ] );
             setcookie( $cookie_key, $hashed, [
                 'expires'  => time() + PWD_LOCK_COOKIE_TTL,
                 'path'     => COOKIEPATH,
                 'httponly' => true,
                 'secure'   => is_ssl(),
                 'samesite' => 'Strict',
             ] );
             $_COOKIE[ $cookie_key ] = $hashed;
             delete_transient( $attempt_key );
         } else {
             set_transient( $attempt_key, $attempts + 1, PWD_LOCK_LOCKOUT_SECONDS );
             $is_error = true;
         }
     }
 }

 // --- 修复点 1:为解锁后的容器添加 ID 锚点 ---
 $stored = $_COOKIE[ $cookie_key ] ?? '';
 if ( $stored && password_verify( $password, $stored ) ) {
     return '<div id="' . esc_attr( $lock_id ) . '" class="pwd-unlocked">' . do_shortcode( $content ) . '</div>';
 }

 $nonce       = wp_nonce_field( 'pwd_lock_action_' . $lock_id, $nonce_key, true, false );
 $error_class = $is_error ? ' pwd-locked--error' : '';
 $attempts_made = (int) get_transient( $attempt_key );
 $remaining     = max( 0, PWD_LOCK_MAX_ATTEMPTS - $attempts_made );

 ob_start();
 ?>
 <!-- 修复点 2:为锁定状态的容器添加 ID 锚点 -->
 <div id="<?php echo esc_attr( $lock_id ); ?>" class="pwd-locked<?php echo esc_attr( $error_class ); ?>" style="scroll-margin-top: 100px;">
     <div class="pwd-locked__icon">🔒</div>
     <p class="pwd-locked__title">此内容已加密</p>
     <p class="pwd-locked__subtitle">输入密码即可查看隐藏内容</p>

     <?php if ( $is_locked_out ) : ?>
         <div class="pwd-locked__error pwd-locked__error--lockout">
             <span>🚫</span>
             <span>错误次数过多,请 15 分钟后重试</span>
         </div>
     <?php elseif ( $is_error ) : ?>
         <div class="pwd-locked__error">
             <span>⚠️</span>
             <span>密码错误,还剩 <?php echo (int) $remaining; ?> 次机会</span>
         </div>
     <?php endif; ?>

     <?php if ( $hint ) : ?>
         <div class="pwd-locked__hint">
             <span>💡</span>
             <span><?php echo esc_html( $hint ); ?></span>
         </div>
     <?php endif; ?>

     <?php if ( ! $is_locked_out ) : ?>
         <!-- 修复点 3:Form action 指向该锚点 -->
         <form method="post" action="#<?php echo esc_attr( $lock_id ); ?>" class="pwd-locked__form">
             <?php echo $nonce; ?>
             <div class="pwd-locked__input-wrapper">
                 <input
                     type="password"
                     name="<?php echo esc_attr( $post_key ); ?>"
                     class="pwd-locked__input"
                     placeholder="请输入密码"
                     autocomplete="current-password"
                     required
                 >
             </div>
             <button type="submit" class="pwd-locked__button">
                 <span>🔓</span>
                 <span>解锁内容</span>
             </button>
         </form>
     <?php endif; ?>
 </div>
 <?php
 return ob_get_clean();

}

add_shortcode( 'pwd_lock', 'password_lock_shortcode' );
}

if ( ! function_exists( 'pwd_lock_disable_cache' ) ) {
function pwd_lock_disable_cache() {
foreach ( array_keys( $POST ) as $key ) {
if ( strpos( $key, 'pwd_input
' ) === 0 ) {
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
define( 'DONOTCACHEPAGE', true );
}
break;
}
}
}
add_action( 'init', 'pwd_lock_disable_cache' );
}

当然,这个只是功能实现代码,觉得样式太丑,还可以补充一个CSS样式

/**
 * 密码保护短代码 [pwd_lock] 配套样式
 * 综合版 — 融合两个版本的最佳实践
 *
 * 包含:渐变按钮、漂浮动画、打印保护、深色模式完整覆盖
 */

/* ==========================================
  错误提示(密码属性未设置时显示)
  ========================================== */
.pwd-error {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  border-radius: 8px;
  background: #fff3f3;
  border: 1px solid #ffc2c2;
  color: #cc0000;
  font-size: 14px;
}

/* ==========================================
  已解锁容器
  ========================================== */
.pwd-unlocked {
  animation: pwd-fade-in 0.4s ease;
}

/* ==========================================
  锁定卡片主容器
  ========================================== */
.pwd-locked {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  max-width: 420px;
  margin: 32px auto;
  padding: 36px 32px;
  border-radius: 16px;
  background: #ffffff;
  box-shadow:
    0 2px 8px rgba(0, 0, 0, 0.06),
    0 8px 32px rgba(0, 0, 0, 0.08);
  border: 1px solid #f0f0f0;
  text-align: center;
  transition: box-shadow 0.2s ease;
}

.pwd-locked:hover {
  box-shadow:
    0 4px 12px rgba(0, 0, 0, 0.08),
    0 12px 40px rgba(0, 0, 0, 0.10);
}

/* 错误状态:红色边框 */
.pwd-locked--error {
  border-color: #ffc2c2;
  box-shadow:
    0 2px 8px rgba(204, 0, 0, 0.06),
    0 8px 32px rgba(204, 0, 0, 0.08);
}

/* ==========================================
  图标
  ========================================== */
.pwd-locked__icon {
  font-size: 42px;
  line-height: 1;
  user-select: none;
  /* 漂浮动画 — 解锁卡片更生动 */
  animation: pwd-float 3s ease-in-out infinite;
}

/* ==========================================
  标题 & 副标题
  ========================================== */
.pwd-locked__title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #1a1a1a;
  letter-spacing: 0.02em;
}

.pwd-locked__subtitle {
  margin: 0;
  font-size: 13px;
  color: #888888;
}

/* ==========================================
  错误提示条
  ========================================== */
.pwd-locked__error {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 10px 14px;
  border-radius: 8px;
  background: #fff3f3;
  border: 1px solid #ffc2c2;
  color: #cc0000;
  font-size: 13px;
  font-weight: 500;
  box-sizing: border-box;
  animation: pwd-shake 0.4s ease;
}

/* 锁定状态(次数耗尽)*/
.pwd-locked__error--lockout {
  background: #fff8f0;
  border-color: #ffcc88;
  color: #994400;
}

/* ==========================================
  提示语
  ========================================== */
.pwd-locked__hint {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  padding: 10px 14px;
  border-radius: 8px;
  background: #f8f9ff;
  border: 1px solid #dde3ff;
  color: #4455cc;
  font-size: 13px;
  box-sizing: border-box;
}

/* ==========================================
  表单
  ========================================== */
.pwd-locked__form {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* 输入框包裹层 */
.pwd-locked__input-wrapper {
  position: relative;
  width: 100%;
}

/* 输入框 */
.pwd-locked__input {
  width: 100%;
  padding: 12px 16px;
  border: 1.5px solid #e0e0e0;
  border-radius: 10px;
  font-size: 15px;
  color: #1a1a1a;
  background: #fafafa;
  outline: none;
  transition:
    border-color 0.2s ease,
    box-shadow 0.2s ease,
    background 0.2s ease;
  box-sizing: border-box;
  /* 字符拉开,方便确认密码输入 */
  letter-spacing: 0.1em;
}

.pwd-locked__input::placeholder {
  color: #bbbbbb;
  letter-spacing: 0;
}

.pwd-locked__input:focus {
  border-color: #4455cc;
  background: #ffffff;
  box-shadow: 0 0 0 3px rgba(68, 85, 204, 0.12);
}

.pwd-locked--error .pwd-locked__input {
  border-color: #ffc2c2;
}

.pwd-locked--error .pwd-locked__input:focus {
  border-color: #cc0000;
  box-shadow: 0 0 0 3px rgba(204, 0, 0, 0.10);
}

/* ==========================================
  提交按钮(渐变质感)
  ========================================== */
.pwd-locked__button {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 12px;
  border: none;
  border-radius: 10px;
  background: linear-gradient(135deg, #4455cc 0%, #6677ee 100%);
  color: #ffffff;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition:
    opacity 0.2s ease,
    transform 0.15s ease,
    box-shadow 0.2s ease;
  box-shadow: 0 2px 8px rgba(68, 85, 204, 0.30);
  letter-spacing: 0.02em;
}

.pwd-locked__button:hover {
  opacity: 0.92;
  transform: translateY(-1px);
  box-shadow: 0 4px 16px rgba(68, 85, 204, 0.38);
}

.pwd-locked__button:active {
  opacity: 1;
  transform: translateY(0);
  box-shadow: 0 1px 4px rgba(68, 85, 204, 0.25);
}

.pwd-locked__button:focus-visible {
  outline: 3px solid rgba(68, 85, 204, 0.40);
  outline-offset: 2px;
}

/* ==========================================
  已解锁内容样式(防止 Markdown / 富文本断裂)
  ========================================== */
.pwd-unlocked p {
  margin: 0 0 12px;
  color: #1a1a1a;
  line-height: 1.7;
}

.pwd-unlocked p:last-child {
  margin-bottom: 0;
}

.pwd-unlocked a {
  color: #4455cc;
  text-decoration: underline;
  text-underline-offset: 2px;
}

.pwd-unlocked a:hover {
  color: #6677ee;
}

.pwd-unlocked code {
  background: #f0f0f5;
  padding: 2px 6px;
  border-radius: 4px;
  font-family: 'Courier New', Courier, monospace;
  font-size: 0.9em;
  color: #4455cc;
}

.pwd-unlocked pre {
  background: #f5f5fa;
  padding: 16px;
  border-radius: 8px;
  overflow-x: auto;
  margin: 12px 0;
  border: 1px solid #e8e8f5;
}

.pwd-unlocked pre code {
  background: none;
  padding: 0;
  color: inherit;
}

.pwd-unlocked img {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
}

.pwd-unlocked ul,
.pwd-unlocked ol {
  margin: 0 0 12px;
  padding-left: 24px;
}

.pwd-unlocked li {
  margin-bottom: 6px;
  line-height: 1.6;
}

.pwd-unlocked blockquote {
  margin: 12px 0;
  padding: 12px 16px;
  border-left: 3px solid #4455cc;
  background: #f8f9ff;
  color: #555;
  border-radius: 0 8px 8px 0;
}

/* ==========================================
  深色模式完整适配
  ========================================== */
@media (prefers-color-scheme: dark) {
  .pwd-error {
    background: #2a1520;
    border-color: #6e2233;
    color: #ff8888;
  }

  .pwd-locked {
    background: #1e1e2e;
    border-color: #2e2e3e;
    box-shadow:
      0 2px 8px rgba(0, 0, 0, 0.30),
      0 8px 32px rgba(0, 0, 0, 0.40);
  }

  .pwd-locked--error {
    border-color: #6e2233;
    box-shadow:
      0 2px 8px rgba(180, 30, 50, 0.20),
      0 8px 32px rgba(180, 30, 50, 0.25);
  }

  .pwd-locked__title {
    color: #e8e8f0;
  }

  .pwd-locked__subtitle {
    color: #7777aa;
  }

  .pwd-locked__input {
    background: #16162a;
    border-color: #3a3a5a;
    color: #e8e8f0;
  }

  .pwd-locked__input:focus {
    background: #1e1e2e;
    border-color: #6677ee;
    box-shadow: 0 0 0 3px rgba(102, 119, 238, 0.20);
  }

  .pwd-locked__input::placeholder {
    color: #55557a;
  }

  .pwd-locked__error {
    background: #2a1520;
    border-color: #6e2233;
    color: #ff8888;
  }

  .pwd-locked__error--lockout {
    background: #2a2010;
    border-color: #6e5022;
    color: #ffaa66;
  }

  .pwd-locked__hint {
    background: #1a1a2e;
    border-color: #2e2e5e;
    color: #8899ee;
  }

  /* 深色模式下解锁内容 */
  .pwd-unlocked p {
    color: #e8e8f0;
  }

  .pwd-unlocked a {
    color: #8899ee;
  }

  .pwd-unlocked code {
    background: #2a2a40;
    color: #8899ee;
  }

  .pwd-unlocked pre {
    background: #16162a;
    border-color: #2e2e3e;
  }

  .pwd-unlocked blockquote {
    background: #1a1a2e;
    border-color: #6677ee;
    color: #94a3b8;
  }
}

/* ==========================================
  移动端适配
  ========================================== */
@media (max-width: 480px) {
  .pwd-locked {
    margin: 20px 16px;
    padding: 28px 20px;
  }

  .pwd-locked__icon {
    font-size: 36px;
  }

  .pwd-locked__title {
    font-size: 16px;
  }
}

/* ==========================================
  打印保护(不泄露受保护内容)
  ========================================== */
@media print {
  .pwd-locked {
    border: 1px dashed #cccccc;
    box-shadow: none;
    color: #888888;
  }

  .pwd-locked__icon,
  .pwd-locked__title,
  .pwd-locked__subtitle,
  .pwd-locked__form,
  .pwd-locked__hint {
    display: none;
  }

  .pwd-locked::after {
    content: '[ 内容受密码保护 — 请在网页中输入密码查看 ]';
    color: #888888;
    font-size: 13px;
    font-style: italic;
  }
}

/* ==========================================
  动画定义
  ========================================== */
@keyframes pwd-fade-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes pwd-float {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
}

@keyframes pwd-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-6px); }
  40% { transform: translateX(6px); }
  60% { transform: translateX(-4px); }
  80% { transform: translateX(4px); }
}

相关推荐

小米路由器AX3600 解锁SSH

小米AIoT路由器AX3600,是一台标准的Wi-Fi 6路由,采用高通第二代Wi-Fi 6方案,更加成熟。全套高通芯片,2.4GHz频段支持2T2R ...

暂无评论