安全加固
角色、防火墙与审计。
安全加固
这一课你将能做到
- 建立「进站净化 → 存库参数化 → 出站转义」的全链路防线,对 XSS/SQL 注入/CSRF 三大攻击逐一落地防御
- 用 nonce + current_user_can 写出防伪造、防越权的表单与 AJAX 处理
- 交出一份生产环境加固清单:密钥、权限、登录保护、更新策略
为什么要学
WP 是全球攻击面最大的 PHP 应用之一:43% 的网站份额让它成为自动化扫描的头号目标。绝大多数被黑站点不是因为 WP 本身,而是插件漏洞 + 开发者不做转义/校验。安全不是选修课——你的站点挂了挂马、SEO 被拉黑,损失立竿见影。
人话:三类攻击各管一段路。SQL 注入管「进」(用户输入拼进了 SQL);XSS 管「出」(脏数据被原样输出,在别人浏览器里执行);CSRF 管「请求来源」(坏人页面替已登录用户发请求)。WP 给你的对策分别是 prepare、esc_* 家族、nonce + 能力检查。
先建立图像
用户输入 ──① sanitize 净化──→ 入库($wpdb->prepare / API)
│
输出到页面 ←──③ esc_* 转义 ←───────┘
写操作请求 ──② nonce 验来源 + current_user_can 验身份──→ 执行
口诀:进净化、出转义、写校验。三道闸缺一不可。
跟着做
步骤 1:出站转义家族(escape)
// 纯文本内容
echo '<p>' . esc_html( $user_input ) . '</p>';
// HTML 属性值(引号安全)
echo '<div class="' . esc_attr( $meta['level'] ) . '">';
// URL(协议白名单,防 javascript: 注入)
echo '<a href="' . esc_url( $meta['link'] ) . '">查看</a>';
// 内联 JS 数据(配 wp_json_encode)
echo '<script>var CFG = ' . wp_json_encode( $cfg ) . ';</script>';
// 富文本:白名单保留标签
echo wp_kses_post( $user_html ); // 允许 a/p/strong 等,剔掉 script
原则是 late escaping:在输出点转义,而不是信任「入库时已净化」——数据来源可能变化,输出点才是最后一道闸。
步骤 2:入站净化家族(sanitize)
$course = array(
'title' => sanitize_text_field( wp_unslash( $_POST['title'] ?? '' ) ),
'email' => sanitize_email( wp_unslash( $_POST['email'] ?? '' ) ),
'level' => sanitize_key( wp_unslash( $_POST['level'] ?? '' ) ), // 小写字母数字下划线
'duration' => absint( wp_unslash( $_POST['duration'] ?? 0 ) ),
);
update_post_meta( $post_id, 'course_meta', $course );
wp_unslash 剥掉 WP 兜底的转义层(magic quotes 遗产),再交给对应 sanitize 函数。
步骤 3:nonce + 能力检查完整链(自定义字段保存)
add_action( 'add_meta_boxes', function () {
add_meta_box( 'qrocmq_course_box', '课程设置', function ( WP_Post $post ) {
wp_nonce_field( 'qrocmq_save_course', 'qrocmq_nonce' ); // ① 表单埋 nonce
$level = get_post_meta( $post->ID, 'level', true );
echo '<select name="qrocmq_level">';
foreach ( array( 'beginner' => '入门', 'advanced' => '进阶' ) as $k => $v ) {
printf( '<option value="%s" %s>%s</option>',
esc_attr( $k ), selected( $level, $k, false ), esc_html( $v ) );
}
echo '</select>';
}, 'course' );
} );
add_action( 'save_post', function ( int $post_id, WP_Post $post ): void {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( wp_is_post_revision( $post_id ) ) return;
// ② 验 nonce:请求是不是从我们的表单发出的
if ( ! isset( $_POST['qrocmq_nonce'] ) ||
! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['qrocmq_nonce'] ) ), 'qrocmq_save_course' ) ) {
return;
}
// ③ 验身份:当前用户有没有权改这篇文章
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
update_post_meta( $post_id, 'level', sanitize_key( wp_unslash( $_POST['qrocmq_level'] ?? '' ) ) );
}, 10, 2 );