Discuz教程网

[二次开发] Discuz X2.5突然出现用户注册限制的触发原因分析

[复制链接]
authicon dly 发表于 2012-10-6 17:47:40 | 显示全部楼层 |阅读模式
DZ最近出现的登录用户名限制问题触发原因是什么?
最近好多家DZ论坛都突然出现了用户注册时出现用户名限制,
当用户在注册窗口注册,
输入的用户名是大于3个字符小于15个字符,
但是弹窗提示
114566201202242543.png

虽然后来DZ通报了解决办法,
是由于后台防灌水功能中的注册表单使用默认导致
只要把注册表单设置为其他,只要没有关键字:username,password这些就没问题
改完以后问题就解决了,虽然解决,但是这个为什么?怎么导致的?
分析一:
看一下具体的文件:
文件:"/template/default/member/register.htm"里

  1. <div class="rfm">
  2. <table>
  3. <tr>
  4. <th><span class="rq">*</span><label for="{$this->setting['reginput']['username']}">{lang username}:</label></th>
  5. <td><input type="text" id="{$this->setting['reginput']['username']}" name="" class="px" tabindex="1" autocomplete="off" size="25" maxlength="15" required /></td>
  6. <td class="tipcol"><i id="tip_{$this->setting['reginput']['username']}" class="p_tip">{lang register_username_tips}</i><kbd id="chk_{$this->setting['reginput']['username']}" class="p_chk"></kbd></td>
  7. </tr>
  8. </table>
  9. </div>
复制代码

文件:/static/js/register.js
  1. function addFormEvent(formid, focus){
  2. var si = 0;
  3. var formNode = $(formid).getElementsByTagName('input');
  4. for(i = 0;i < formNode.length;i++) {
  5. if(formNode[i].name == '') {
  6. formNode[i].name = formNode[i].id;
  7. stmp[si] = i;
  8. si++;
  9. }
  10. if(formNode[i].type == 'text' || formNode[i].type == 'password'){
  11. formNode[i].onfocus = function(){
  12. showInputTip(!this.id ? this.name : this.id);
  13. }
  14. }
  15. }
  16. ......
复制代码

以上HTML这段代码是显示注册用户名的表单,可以发现name属性是空的,而id是可以后台配置的用户名ID,而在登录时/static/js/register.js这个脚本里的addFormEvent()函数会对注册表单进行检测,在检测时会对用户名、密码等name为空的属性,并把其ID的值赋给name属性,然后后台PHP就通过这个name属性来接收表单信息。而当改成弹窗注册时,应该是没有执行以上这段代码对name进行赋值,所以后台就没有接收到name为空,所以就会显示问题所示的提示。
分析二:

我来给你说一下,首先看后台注册表名设置:
  1. if(!preg_match('/^[A-z]\w+?$/', $settingnew['reginput']['username'])) {
  2.         $settingnew['reginput']['username'] =  'username';
  3.     }
复制代码

如果你不设置(默认)的话程序会默认username为字段名,然后保存到数据库。
在dx入口程序class_core.php里开始会调用建立缓存的函数function _init_setting(),里面有这么一条语句
!empty($this->cachelist) && loadcache($this->cachelist);//如果缓存存在,就加载缓存。
而function loadcache($cachenames, $force = false)这个东东呢,又调用function cachedata($cachenames)。该函数是读缓存文件的,看下面一句:
  1. if(!@include_once(DISCUZ_ROOT.'./data/cache/cache_'.$cachename.'.php')) {
  2.         $lostcaches[] = $cachename;
  3.     }
复制代码

当你第一次进入dx或着在后台清缓存的时候,程序会自动重新生成新缓存,而dx生成环境缓存的文件就是cache_setting.php,打开该文件你会看到首先一个函数function build_cache_setting()。哦,这东东就是建立dx环境缓存的函数呀!里面有这么一段代码引起了我的注意:
  1. $reginputbwords = array('username', 'password', 'password2', 'email');
  2.     if(in_array($data['reginput']['username'], $reginputbwords) || !preg_match('/^[A-z]\w+?$/', $data['reginput']['username'])) {
  3.         $data['reginput']['username'] = random(6);
  4.     }
  5.     if(in_array($data['reginput']['password'], $reginputbwords) || !preg_match('/^[A-z]\w+?$/', $data['reginput']['password'])) {
  6.         $data['reginput']['password'] = random(6);
  7.     }
  8.     if(in_array($data['reginput']['password2'], $reginputbwords) || !preg_match('/^[A-z]\w+?$/', $data['reginput']['password2'])) {
  9.         $data['reginput']['password2'] = random(6);
  10.     }
  11.     if(in_array($data['reginput']['email'], $reginputbwords) || !preg_match('/^[A-z]\w+?$/', $data['reginput']['email'])) {
  12.         $data['reginput']['email'] = random(6);
  13.     }
复制代码

游客,如果您要查看本帖隐藏内容请回复

耶,name值咋为空呢,id="{$this->setting['reginput']['username']}"又引起了我的注意,$this->setting变量是在入口程序里读的cache缓存,也就是上面的$data['reginput']['username'] = random(6);接着分析
当你填写完注册信息后register.js会ajaxpost调用addFormEvent(formid, focus),而这个函数里会把id赋给name
  1. if(formNode.name == '') {
  2.         formNode.name = formNode.id;
  3.         stmp[si] = i;
  4.         si++;
  5.     }
复制代码

到这里我明白了,在点注册提交后js把$this->setting['reginput']['username']的值才赋给name值,然后再看class_member.php是如何处理的。
function on_register()函数开始有这几句代码:
  1. $_G['gp_username'] = $_G['gp_'.$this->setting['reginput']['username']];
  2. $_G['gp_password'] = $_G['gp_'.$this->setting['reginput']['password']];
  3. $_G['gp_password2'] = $_G['gp_'.$this->setting['reginput']['password2']];
  4. $_G['gp_email'] = $_G['gp_'.$this->setting['reginput']['email']];
  5. 上面是接收注册信息数据,下面是判断用户名长度。
  6. $usernamelen = dstrlen($username);
  7.     if($usernamelen < 3) {
  8.         showmessage('profile_username_tooshort');
  9.     } elseif($usernamelen > 15) {
  10.         showmessage('profile_username_toolong');
  11.     }
复制代码

到这里我明白了,dx搞这么复杂就是为了防止注册机的,你注册机每次给我传username、password、password2、email来,我靠,我每次都random(6),我看你咋搞!
不管你明不明白,反正我是明白了!



上一篇:Discuz X2.5多个论坛性能优化经验分享
下一篇:Discuz X2.5通过ucenter整合别的网站
authicon 708090 发表于 2012-11-13 01:51:10 | 显示全部楼层
强烈支持楼主ing……
authicon 曾经 发表于 2012-11-25 15:40:04 | 显示全部楼层
好东西好了好久
authicon Super_Cool 发表于 2013-1-5 13:21:38 | 显示全部楼层
强烈支持楼主ing……
authicon csacx 发表于 2014-11-15 00:55:12 | 显示全部楼层
er.js会ajaxpost调用addFormEvent(formid, focus),而这个函数里
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

1314学习网 ( 浙ICP备10214163号 )

GMT+8, 2025-5-2 01:25

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表