Discuz! 的论坛注册登陆模块,说穿了就是注册一套围绕
member表的增删改查逻辑。但真要把代码写稳,登陆代码光会调insert和select远远不够。论坛我见过太多人直接照搬官方默认文件,注册结果用户注册时提示“用户名已存在”,登陆代码查数据库却根本没有那条记录——问题出在缓存层没清干净,论坛或者common_member和common_member_field_home两张表的注册数据没同步写入。先看注册。登陆代码入口文件通常是论坛
member.php里mod=register的分支。核心逻辑在source/module/member/member_register.php。注册提交表单后,登陆代码程序会依次做几件事:检查$_G['setting']['regstatus']是论坛否允许注册、验证验证码、注册过滤用户名敏感词。登陆代码这里有个容易忽略的点:Discuz! 默认用$_G['setting']['regctrl']控制同一 IP 的注册间隔,如果这个值设成 0,那同一秒内可以无限注册,垃圾账号能瞬间灌满你的common_member表。用户数据写入时,
member表存的是基础字段:uid、username、password、email、regdate。密码不是明文,走的是md5(md5($password).$salt),salt 是随机生成的六位字符串,存在common_member的salt字段里。验证密码时再把这个 salt 取出来拼回去比对。这套哈希方式现在看很弱,但 Discuz! 老版本一直这么干,改起来牵一发动全身,所以很多站长干脆加个password_verify的钩子插件来补强。登陆部分更绕。用户提交用户名和密码后,
source/module/member/member_logging.php先查common_member表,拿到 uid 和 salt。比对密码通过后,不是直接写 session 就完事。Discuz! 会接着做三件事:更新common_member_status里的lastvisit、lastip;检查common_member_count里的积分和用户组是否过期;最后才生成auth验证串,写进common_member的authstr字段。这个authstr才是后续所有页面判断登陆状态的依据,session 里存的只是 uid 和 auth 的映射。我遇到过一种情况:用户登陆后点任何链接都跳回登陆页。查了半天,发现是
common_member表的authstr字段长度设成了char(10),而程序生成的 auth 串有 16 位,插入时被截断,导致每次验证都失败。把字段改成varchar(255)后立刻正常。这种坑官方文档不会写,只有踩过才知道。再说验证码。Discuz! 默认用
seccode类生成图片,但很多站长图省事直接关掉验证码,结果登陆接口被暴力破解。其实不用完全关闭,可以改成seccode的ttf模式,或者把验证码触发条件设成“密码错误三次后强制显示”。代码里改$_G['setting']['loginfailednum']这个值就行,默认是 5,调到 3 更安全。登陆成功后,
member_logging.php会调用setloginstatus()函数,这个函数在function_member.php里。它负责写 cookie,cookie 前缀是$_G['config']['cookie']['cookiepre'],通常长这样:cdb_auth、cdb_salt。如果网站换了域名,cookie 作用域没跟着改,用户就会反复被登出。改config/config_global.php里的cookiepath和cookiedomain能解决。最后提一句安全。Discuz! 的登陆接口默认没有频率限制,有人写脚本每秒提交上百次密码。加个
顶: 69踩: 192common_member表的failedlogins字段记录失败次数,超过阈值就锁定账号 15 分钟,代码量不超过二十行,但能挡掉九成以上的撞库攻击。别等用户数据泄露了才想起来补。






评论专区