ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WordPress内容锁定:短代码+密码+Cookie实现公众号导流

WordPress内容锁定:短代码+密码+Cookie实现公众号导流 简介由博客 dsdiss.com 开发的一款名为 Dsdiss Verification 的 WordPress 插件核心用途是隐藏文章部分内容访客关注公众号并获取密码后方可查看从而帮助内容型网站站长完成微信公众号引流。后台新增“二维码设置”页面可配置验证密码、提示文字与二维码图片通过 [protected] 短代码在文章中标注受保护片段验证成功后会通过 cookie 记录状态使用门槛低非技术型运营者也能借助后台完成配置。压缩包为 zip 格式整体仅 4KB共 3 个文件PHP 主文件负责后台设置与短代码解析JS 脚本处理前端验证交互CSS 文件控制隐藏区域样式。插件包虽小但完整覆盖了从文章内容保护、用户输入密码、写入 cookie 到显示隐藏内容的闭环流程也便于开发者理解 WordPress 插件开发中的设置 API、短代码注册、静态资源引入及验证状态管理等常见知识点。目前已有 48 人学习下载适合微信公众号运营者、WordPress 站长以及希望学习内容隐藏类插件实现的初级开发者参考。1. 不只是隐藏微信公众号导流插件的验证机制与场景如果一个 WordPress 站点只是把文章截断用户根本不会去扫码关注公众号。真正让人愿意掏出手机扫码的是那种“内容就在眼前但被锁住”的微妙心理。Dsdiss Verification 正是这类插件里非常轻量的一款它的核心逻辑只有一个短代码[protected]把文章某段内容包起来访客从公众号那边拿到密码后输入验证通过验证就靠 Cookie 记住状态刷新后内容直接可见。它不引入会员体系不校验微信 openid也不改文章表结构对现有站点几乎没有侵入性。适合放课程资料、下载链接、活动代码或者临时需要访问门槛的文章也适合运营人员用来拉公众号的关注量。由于整个流程只有“密码 Cookie 短代码”三件事排错和二次开发都容易。2. 拆解 dsdiss-verification.php设置项注册与短代码定义把压缩包解压后核心内容就三个文件dsdiss-verification.php是主入口style.css控制锁定框样式script.js负责前端交互。按 WordPress 插件惯例整个目录复制到/wp-content/plugins/dsdiss-verification/即可被识别。主文件开头通常有一份插件头注释用来声明插件的名称和启用入口。/* Plugin Name: Dsdiss Verification Description: 隐藏文章部分内容验证密码后通过 Cookie 解锁 Version: 1.0 */插件头注释是 WordPress 识别插件的基础没有它后台插件列表会直接报“文件内容错误”。下面的资源加载和设置项注册都依赖这个主文件正常载入。理解了这个入口后面看短代码和 AJAX 逻辑才不会乱。2.1 插件文件结构与加载入口文件作用dsdiss-verification.php插件主入口负责短代码注册、后台菜单、设置项和 AJAX 回调style.css锁定提示框、二维码图片、表单的默认样式script.js表单提交、AJAX 验证、写 Cookie、刷新页面资源加载是第一个关键点。原文插件会在前台页面同时引入 CSS 和 JS并提前准备好 AJAX 地址。常见做法是这样function dsdiss_enqueue_assets() { wp_enqueue_style(dsdiss-verification, plugin_dir_url(__FILE__) . style.css, array(), 1.0); wp_enqueue_script(dsdiss-verification, plugin_dir_url(__FILE__) . script.js, array(jquery), 1.0, true); wp_localize_script(dsdiss-verification, dsdiss_ajax, array( ajax_url admin_url(admin-ajax.php), )); } add_action(wp_enqueue_scripts, dsdiss_enqueue_assets);这里用plugin_dir_url(__FILE__)而不是硬编码路径是因为插件目录可能被重命名硬编码在迁移时第一个出问题。wp_localize_script把 AJAX 地址暴露给 JS 里的dsdiss_ajax.ajax_url避免在脚本里写死域名。加载顺序上JS 放到页脚位置不阻塞文章页首屏渲染。提示如果前台样式没有生效优先在浏览器开发者工具里看style.css是否返回 404再检查插件目录名是否和代码拼出来的路径一致。2.2 后台菜单与设置项注册后台菜单的作用是让管理员能设置验证密码、提示内容和二维码图片。原插件在 WordPress 后台添加了一个“二维码设置”菜单对应的结构可以还原为add_action(admin_menu, function () { add_menu_page( 二维码设置, 二维码设置, manage_options, dsdiss-verification, dsdiss_render_options_page ); }); add_action(admin_init, function () { register_setting(dsdiss_settings_group, dsdiss_password); register_setting(dsdiss_settings_group, dsdiss_tip_text); register_setting(dsdiss_settings_group, dsdiss_qrcode_url); });add_menu_page的参数分别是页面标题、菜单标题、用户权限、菜单别名、回调函数。这里使用manage_options限制为管理员权限避免订阅者进入后台设置页。register_setting的第一个参数是设置组名必须和后面保存表单里settings_fields填写的组名完全一致否则 WordPress 会拒绝保存并提示“操作不合法”。从存储设计看三个值各自存成独立 option而不是合成一个数组是为了读取时直接用get_option拿字符串省去解析数组的步骤。缺点是设置项变多后会占更多wp_options表记录单站点问题不大多站点则需要考虑聚合存储。2.3 短代码 [protected] 的解析与权限判断短代码是整个插件的核心。文章编辑器里写了[protected]...[/protected]WordPress 解析时会调用注册的回调函数。原插件的判断逻辑很直白读取全局密码检查 Cookie 中的值与密码指纹是否一致一致就输出隐藏内容否则渲染锁定提示和表单。add_shortcode(protected, dsdiss_protected_render); function dsdiss_protected_render($atts, $content null) { $password get_option(dsdiss_password, ); $verified isset($_COOKIE[dsdiss_verified]) $_COOKIE[dsdiss_verified] md5($password); if ($verified) { return do_shortcode($content); } $tip get_option(dsdiss_tip_text, 请关注公众号后获取密码); return sprintf( div classdsdiss-locked%sform iddsdiss-verify-forminput typepassword namedsdiss_password /button typesubmit验证/button/form/div, esc_html($tip) ); }这里用md5($password)做 Cookie 标记只是防止明文密码直接出现在前端严格来说它不是安全方案。因为 md5 值等于密码指纹抓到 Cookie 后可以用彩虹表反查。生产环境我更倾向于用wp_hash或hash_hmac(sha256, $password, wp_salt())生成标记。另外$content必须经过do_shortcode否则隐藏内容里嵌套的其他短代码不会解析。注意$atts参数在当前版本没有实际参与判断但它为后续扩展留下了空间比如给短代码加id属性实现不同文章不同密码。这一点在后文会展开。3. 前端验证链路从密码框到 Cookie 标记后台逻辑只负责判断“当前请求是否已通过验证”真正的交互发生在script.js。用户点击验证按钮后JS 把密码提交到 admin-ajax.phpPHP 返回成功标记JS 把标记写入 Cookie最后刷新页面让短代码重新渲染。整个过程不需要跳转体验比传统表单提交更顺畅。3.1 admin-ajax 接口与密码校验WordPress 插件最常用的 AJAX 入口是admin-ajax.php。Dsdiss Verification 注册了wp_ajax_和wp_ajax_nopriv_两个钩子因为文章访客大多没有注册账号必须允许匿名请求。add_action(wp_ajax_dsdiss_verify, dsdiss_handle_verify); add_action(wp_ajax_nopriv_dsdiss_verify, dsdiss_handle_verify); function dsdiss_handle_verify() { $input isset($_POST[password]) ? wp_unslash($_POST[password]) : ; $pass get_option(dsdiss_password, ); if ($input $pass) { wp_send_json_success(array( token md5($pass) )); } wp_send_json_error(array(message 密码错误请重新核对公众号里的提示。), 403); }wp_send_json_success会自动输出 JSON 并结束请求比手动拼接 JSON 再wp_die省事。wp_unslash是必须的因为 WordPress 会默认给$_POST加 slashes如果不处理和 option 里保存的密码比对时大概率失败。从安全角度这个接口缺少 nonce 校验意味着理论上有爆破风险。自己部署时建议在表单里加wp_nonce_field然后用check_ajax_referer校验。3.2 script.js 的状态写入与刷新策略script.js 的任务是拦截表单提交、发起 AJAX、写 Cookie、刷新页面。最直接的做法是jQuery(function($) { $(document).on(submit, #dsdiss-verify-form, function(e) { e.preventDefault(); var pwd $(this).find(input[namedsdiss_password]).val(); $.post(dsdiss_ajax.ajax_url, { action: dsdiss_verify, password: pwd }).done(function(res) { if (res.success) { document.cookie dsdiss_verified res.data.token ; path/; max-age3600; SameSiteLax; window.location.reload(); } else { alert(res.data.message); } }).fail(function() { alert(验证请求失败请检查网络后重试。); }); }); });max-age3600表示 Cookie 有效期 1 小时单位是秒如果公众号固定每天更新口令可以调整到 86400。path/让 Cookie 在整个站点内生效这样用户从文章甲跳到文章乙只要两篇文章共用同一个密码就不会重复验证。子目录安装站点要注意路径设置否则会出现“这个页面验证成功另一个页面又锁住”的问题。这里不设置HttpOnly是因为 JS 需要显式写入 Cookie。代价是如果站点存在 XSS 漏洞攻击者也能读到这个验证标记。更稳妥的方案是让 PHP 端校验后直接setcookie再跳回当前页但那样交互会多一次跳转。原插件选择的是 JS 写 Cookie胜在简洁。3.3 Cookie 参数与常见认知误区Cookie 属性参数值影响namedsdiss_verified对应 PHP 端读取$_COOKIE[dsdiss_verified]valuemd5(password)避免明文密码进入前端但不能防止重放path/全站生效子目录站点应使用 COOKIEPATHmax-age3600过期时间太长导致验证状态长期有效SameSiteLax阻止第三方站携带该 Cookie 发出跨站请求一个常被忽略的点刷新页面后短代码回调里只比较$_COOKIE[dsdiss_verified] md5($password)并没有校验这个 Cookie 是否来自当前站点。浏览器本身会按域名隔离 Cookie所以跨站点伪造风险不高但同网段用户如果抓包拿到 Cookie 值在自己的浏览器里伪造同样值也能生效。这就是密码不能设置太简单的原因最好混合字母和数字。4. 二维码设置与后台参数调优设置页看起来只有三个字段但每个字段都直接决定用户是否会扫码。很多部署后转化率低的案例问题都出在提示文本太含糊、二维码加载失败或者表单和二维码不在同一屏。4.1 三个核心字段的作用与取值建议后台“二维码设置”页需要维护以下三个配置项设置项标识显示名称说明dsdiss_password验证密码公众号自动回复或图文消息中给出的口令dsdiss_tip_text提示内容锁定框中的引导文字需要明确写出获取方式dsdiss_qrcode_url二维码图片 URL公众号二维码图片的完整 URL建议使用 HTTPS 绝对地址密码建议用类似2025-x7k9这样的短口令不要用超长随机字符串用户从公众号复制到网页的过程很容易出错。提示文字要写清楚步骤例如“打开微信扫一扫右侧二维码关注后回复 dsdiss 获取访问密码”。二维码图片 URL 必须填完整地址不能写相对路径否则在部分浏览器和 App 内打开时图片会裂。锁定框里需要通过短代码渲染二维码。常见做法是在返回表单前把二维码 URL 拼进提示区域$qr get_option(dsdiss_qrcode_url, ); if ($qr) { $tip . sprintf( img src%s classdsdiss-qrcode alt公众号二维码 /, esc_url($qr) ); }这样二维码和表单就出现在同一个.dsdiss-locked容器里。样式方面style.css里通常会把容器改成 flex 布局让文字、二维码、验证按钮在桌面端并排在移动端自动折行。二维码图片建议限制max-width: 180px避免撑破文章内容宽度。4.2 后台表单渲染与保存逻辑设置表单的标准写法是function dsdiss_render_options_page() { ? div classwrap h1二维码设置/h1 form methodpost actionoptions.php ?php settings_fields(dsdiss_settings_group); ? table classform-table trth验证密码/thtdinput namedsdiss_password value?php echo esc_attr(get_option(dsdiss_password)); ? //td/tr trth提示内容/thtdtextarea namedsdiss_tip_text?php echo esc_textarea(get_option(dsdiss_tip_text)); ?/textarea/td/tr trth二维码图片 URL/thtdinput namedsdiss_qrcode_url value?php echo esc_attr(get_option(dsdiss_qrcode_url)); ? //td/tr /table ?php submit_button(); ? /form /div ?php }表单的action指向options.php由 WordPress 后台自动处理保存逻辑。settings_fields输出 nonce 和option_page隐藏字段名称必须与register_setting的组名一致。填写字段时注意使用esc_attr和esc_textarea防止后台设置页被恶意注入脚本。如果后面想支持多密码可以把dsdiss_password改成 JSON 字符串存储但读取时要json_decode并在短代码回调里根据$atts[id]选择对应密码。未指定id时最好回落到默认密码保证旧文章不用改。4.3 部署中的常见坑与排查方向第一个最容易遇到的坑是缓存。站点启用页面缓存后用户第一次看到锁定状态时页面被缓存验证成功刷新后仍然返回缓存版本Cookie 生效不了。处理办法是让缓存插件排除带dsdiss_verifiedCookie 的请求或者干脆关闭含有[protected]页面的缓存。轻量站点可以直接禁用该文章页缓存。第二个坑是二维码加载失败。如果后台填的是/wp-content/uploads/qr.png这样的相对路径在前台网页上也许能访问但在微信内置浏览器里可能因为基础路径变化被解析成错误地址。见到这种情况应改成https://your-domain.com/wp-content/uploads/qr.png的绝对地址并避免使用短链接。第三个坑是the_content过滤顺序。有的主题在输出文章内容时会对包含短代码的文本做wp_kses或其他转义导致返回的 HTML 被吞掉。定位办法先禁用所有其他插件只保留本插件如果锁定框正常显示再逐个开启其他插件找到冲突源。5. 扩展让 [protected] 支持多篇文章不同密码很多运营者做到第二个活动就会遇到问题一篇活动文章一个密码才能区分不同渠道的关注效果。原插件只支持一个全局密码但短代码的属性参数本身就适合做这个扩展。比如把[protected idcourse-a]解析成读取dsdiss_pass_course-a未指定id时回落到全局密码。5.1 多密码短代码的实现扩展后的短代码回调可以写成这样add_shortcode(protected, function ($atts, $content null) { $atts shortcode_atts(array(id default), $atts, protected); $password default $atts[id] ? get_option(dsdiss_password, ) : get_option(dsdiss_pass_ . $atts[id], ); $verified isset($_COOKIE[dsdiss_verified_ . $atts[id]]) $_COOKIE[dsdiss_verified_ . $atts[id]] md5($password); if ($verified) { return do_shortcode($content); } $tip get_option(dsdiss_tip_text, 请关注公众号获取密码); return div classdsdiss-locked . esc_html($tip) . /div; });这里的关键是 Cookie 名也带上了id避免多篇文章密码互相覆盖。如果忽略这一点用户验证完 A 文章后B 文章也会被误判为已解锁。后台的接口回调同样要接收一个shortcode_id字段返回对应密码的 token否则前端的 Cookie 永远写不进去。5.2 验证方法与样式细节部署后可以用浏览器开发者工具验证打开“应用”面板查看dsdiss_verified_course-a的 value 是否等于对应密码的 md5 值。确认一致后刷新页面如果该篇文章的隐藏内容可见而另一篇使用不同id的文章仍然锁定说明隔离逻辑正确。最后一个细节锁定框里的二维码图片建议在style.css里设置max-width: 180px; border-radius: 8px;并让图片与提示文字垂直居中。小屏手机用户扫码时尺寸过大的二维码会被截断影响整体转化率。本文还有配套的精品资源点击获取
返回列表