要实现Discuz!账号单点登录限制,可通过以下两种方式实现:
一、数据库字段+登录校验方案(推荐)
1. 修改用户表结构
在pre_common_member表中新增两个字段:
- ALTER TABLE pre_common_member ADD COLUMN `session_token` CHAR(32) NOT NULL DEFAULT '';
- ALTER TABLE pre_common_member ADD COLUMN `last_active` INT(10) UNSIGNED NOT NULL DEFAULT '0';
复制代码
2. 扩展登录验证类
编辑文件`source/class/class_member.php`,在登录成功处添加:
- // 在function on_login()方法中找到登录成功的位置
- $authkey = md5($_G['config']['security']['authkey'] . microtime() . random(10));
- C::t('common_member')->update($uid, array('session_token' => $authkey));
复制代码
3. 增加全局验证(核心)
创建新文件`source/plugin/restrict_login/restrict_login.class.php`:
- class plugin_restrict_login {
- public function global_header() {
- global $_G;
- if($_G['uid']) {
- $member = C::t('common_member')->fetch($_G['uid']);
- if($member['session_token'] !== $_G['member']['session_token']) {
- require_once libfile('function/member');
- clearcookies();
- showmessage('您的账号已在其他设备登录', '', array(), array('login' => 1));
- }
- // 更新最后活跃时间
- if(TIMESTAMP - $member['last_active'] > 300) {
- C::t('common_member')->update($_G['uid'], array('last_active' => TIMESTAMP));
- }
- }
- }
- }
复制代码
4. 扩展退出处理
在用户退出时清空token:
- // 找到function on_logout()方法
- C::t('common_member')->update($_G['uid'], array('session_token' => ''));
复制代码
二、Session文件监控方案(适合无法修改数据库的环境)
1. 创建监听类`source/class/restrict/RestrictLogin.php`:
- class RestrictLogin {
- const SALT = 'your_custom_salt';
-
- public static function generateSessionId($uid) {
- return md5($uid . self::SALT . $_SERVER['HTTP_USER_AGENT']);
- }
- public static function validate() {
- $uid = getglobal('uid');
- if($uid) {
- $sessionFile = DISCUZ_ROOT.'./data/session/'.sesskey();
- if(file_exists($sessionFile)) {
- $officialId = self::generateSessionId($uid);
- if(basename($sessionFile) != $officialId) {
- self::forceLogout();
- }
- }
- }
- }
- private static function forceLogout() {
- require_once libfile('function/member');
- clearcookies();
- showmessage('检测到多设备登录,已强制退出', '', array(), array('login' => 1));
- }
- }
复制代码
2. 在全局初始化中调用验证:
编辑`source/class/discuz/discuz_application.php`,在_init_user方法末尾添加:
- RestrictLogin::validate();
复制代码
三、混合增强方案(推荐)
结合上述两种方案,并增加以下优化:
1. 实时心跳检测:通过AJAX每5分钟发送活跃状态
2. 登录日志记录:记录设备指纹和地理位置
3. Token加密存储:使用openssl加密存储会话凭证
4. 管理员白名单功能:允许特定用户组多设备登录
注意事项:
1. 需要修改Discuz!的session存储机制为数据库存储,增强可靠性
2. 设备指纹应包含:UserAgent+IP段(前3段)+屏幕分辨率哈希
3. 对移动端APP需要特殊处理,采用OAuth机制
4. 需要处理跨子站点的单点登录需求
具体实现代码较为复杂,建议在DZ插件网搜索"全局会话管控"或"强制单点登录"插件,选择商业解决方案可获取完整功能实现,包括:登录设备管理、异常登录提醒、会话实时监控等功能模块。
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。 |