WordPress在线课程:基于Token的无账号访问与进度追踪方案咨询
无注册用户的WordPress课程访问控制与进度追踪方案
针对你提到的无需注册即可控制课程访问、追踪学习进度的需求,我有过类似实践,以下是具体实现方案和关键注意事项:
一、核心Token与个性化URL生成
- Token结构设计:采用「用户标识-课程ID-时间戳-HMAC签名」的组合,避免明文存储敏感信息。用户标识可以是邮箱、自定义短ID(比如给每个需访问的用户生成唯一标识),签名用WordPress内置的
wp_hash()函数生成,确保Token无法被篡改。示例Token:guest_001-105-1718000000-a1b2c3d4e5f6 - 个性化URL生成:将Token作为查询参数拼接到课程页面URL,比如:
https://your-site.com/course/wordpress-basics?access_token=guest_001-105-1718000000-a1b2c3d4e5f6 - 生成工具:可以在WordPress后台做一个简易生成界面,输入用户标识和课程ID,自动生成带Token的URL,方便批量创建。
二、Token验证与身份识别
在WordPress中通过钩子实现Token验证,确保只有持有有效Token的用户能访问对应课程:
add_action('template_redirect', 'verify_course_access_token'); function verify_course_access_token() { // 仅在课程自定义类型页面且存在access_token参数时触发 if (!is_singular('course') || !isset($_GET['access_token'])) { return; } $token = sanitize_text_field($_GET['access_token']); $parts = explode('-', $token); // 验证Token格式是否正确 if (count($parts) !== 4) { wp_redirect(home_url('/access-denied/')); exit; } list($temp_user_id, $course_id, $timestamp, $signature) = $parts; $current_course_id = get_the_ID(); // 验证Token对应的课程是否为当前访问的课程 if ((int)$course_id !== $current_course_id) { wp_redirect(home_url('/access-denied/')); exit; } // 验证Token有效期(示例:7天) if (time() - (int)$timestamp > 7 * 24 * 3600) { wp_redirect(home_url('/token-expired/')); exit; } // 重新生成签名,验证Token未被篡改 $expected_signature = wp_hash("$temp_user_id-$course_id-$timestamp"); if ($signature !== $expected_signature) { wp_redirect(home_url('/invalid-token/')); exit; } // 验证通过,将临时身份存储到会话 if (!session_id()) { session_start(); } $_SESSION['temp_user_id'] = $temp_user_id; $_SESSION['allowed_course_id'] = $course_id; }
三、学习进度追踪实现
- 自定义数据库表存储进度:创建一张专门的临时进度表,避免和WordPress默认表冲突。可以通过以下SQL语句创建(在主题的
functions.php里用dbDelta执行):
add_action('after_setup_theme', 'create_temp_progress_table'); function create_temp_progress_table() { global $wpdb; $table_name = $wpdb->prefix . 'temp_course_progress'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id mediumint(9) NOT NULL AUTO_INCREMENT, temp_user_id varchar(50) NOT NULL, course_id mediumint(9) NOT NULL, completed_chapters text NOT NULL, total_time int(11) DEFAULT 0, last_access datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY temp_user_course (temp_user_id, course_id) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); }
- 进度更新触发:通过前端AJAX请求,在用户完成章节、观看完视频等操作时,调用后端接口更新进度:
// 注册AJAX接口(允许未登录用户调用) add_action('wp_ajax_update_course_progress', 'update_course_progress'); add_action('wp_ajax_nopriv_update_course_progress', 'update_course_progress'); function update_course_progress() { // 验证临时身份 if (!session_id()) { session_start(); } if (!isset($_SESSION['temp_user_id']) || !isset($_SESSION['allowed_course_id'])) { wp_send_json_error('未授权访问'); exit; } $temp_user_id = sanitize_text_field($_SESSION['temp_user_id']); $course_id = (int)$_SESSION['allowed_course_id']; $chapter_id = sanitize_text_field($_POST['chapter_id']); $add_time = (int)$_POST['add_time']; // 本次学习时长,单位秒 global $wpdb; $table_name = $wpdb->prefix . 'temp_course_progress'; // 查询现有进度 $existing_progress = $wpdb->get_row($wpdb->prepare( "SELECT completed_chapters, total_time FROM $table_name WHERE temp_user_id = %s AND course_id = %d", $temp_user_id, $course_id )); // 更新已完成章节(用逗号分隔存储) $completed_chapters = $existing_progress ? $existing_progress->completed_chapters : ''; if (!str_contains($completed_chapters, $chapter_id)) { $completed_chapters = $completed_chapters ? "$completed_chapters,$chapter_id" : $chapter_id; } // 更新总学习时长 $total_time = $existing_progress ? $existing_progress->total_time + $add_time : $add_time; // 插入或更新进度记录 $wpdb->replace( $table_name, array( 'temp_user_id' => $temp_user_id, 'course_id' => $course_id, 'completed_chapters' => $completed_chapters, 'total_time' => $total_time ), array('%s', '%d', '%s', '%d') ); wp_send_json_success('进度更新成功'); }
- 进度展示:在课程页面读取当前用户的进度数据,展示已完成章节、学习时长等信息:
function get_temp_user_progress() { if (!session_id()) { session_start(); } if (!isset($_SESSION['temp_user_id']) || !isset($_SESSION['allowed_course_id'])) { return false; } global $wpdb; $table_name = $wpdb->prefix . 'temp_course_progress'; $progress = $wpdb->get_row($wpdb->prepare( "SELECT * FROM $table_name WHERE temp_user_id = %s AND course_id = %d", $_SESSION['temp_user_id'], $_SESSION['allowed_course_id'] )); return $progress; }
在课程模板中调用这个函数,渲染进度信息即可。
四、关键注意事项(已知安全性不足前提下)
- Token转发风险:因为URL可直接分享,任何人拿到链接都能访问对应课程。可以通过设置Token有效期(比如7天)降低风险,或者在生成URL时提示用户不要转发。
- 会话管理:确保会话在用户关闭浏览器后失效,避免他人复用会话访问。如果服务器端会话配置有问题,可以改用临时Cookie存储身份信息,设置较短的过期时间。
- 数据清理:定期清理过期的进度记录(比如删除3个月未访问的记录),避免数据库冗余。
- 性能优化:如果用户量较大,建议给临时进度表的
temp_user_id和course_id字段建立联合索引,提升查询速度。 - 权限兼容:确保WordPress的默认权限系统不会拦截临时用户的AJAX请求,比如在
wp_ajax_nopriv_*钩子中处理未登录用户的请求。 - 统计需求:如果需要汇总学习数据,提前设计好表结构,方便后续导出或统计分析。
内容的提问来源于stack exchange,提问作者LINFOR_2000
相关产品推荐
相关产品推荐

