搞 WordPress 的都知道:后台「可见性」里只有「公开」和「密码保护」两个按钮。
可我就想问:能不能只加密其中一段?
比如把微信号、服务器 IP、未公开的草稿链接藏起来,其余内容正常阅读。
答案在短代码里。那些「关注公众号获取密码」的增长黑客玩法,内核全是它。但我只想要个干净的「部分加密」,不想整关注、不想存 Session、不想写后台设置页。这个放在以前估计会难道一批人,但是現在AI技术的成熟,催生了新的路径:vibe codding
直接自然语言和 AI提需求:「帮我写个短代码,内容加密、Cookie 记录解锁状态、前端输入框自动聚焦」,复制进 functions.php,三分钟上线。
/**
- 密码保护短代码
*/
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); }
}

暂无评论
要发表评论,您必须先 登录