你现在的位置:首页 > PHP网站建设知识库 > phpbb > 正文

phpbb开发之:如何实现phpbb3的密码加密

PHPBB3做为一个优秀的论坛流传了很多年,近来其新出的V3(Olympus)和以前的V2有很多地主不同,在做phpbb开发时,如何将之集成(integrate)到你的网站上,并与你网站上的数据库融为一体,这无非就是如下两项工作:

a、将本站的用户数据库与phpbb3的USERS_TABLE合二为一,集成起来。

b、将本站的用户登录与注册程序与phpbb3的注册登录程序集成起来。

听起来似乎很容易,其实不然,这里还是有些麻烦事的,请一步步跟我来:

1、cookies的集成:

cookie主要用于用户登录,以记录用户在该站点的权限及操作等。

phpbb3在运行过程中启动了若干个cookie,但这里我们只关心其以下两个COOKIE:    cookie_name_u, cookie_name_sid,因为这两个cookie是在登录后启动的,如果没有正确的设置这两个cookie,就会失去用户功能,因此我们重点需要 关心这两个cookie。

这里cookie_name是在安装phpbb3时设置的,具体在你的站点里叫什么名字,请查阅你的数据库config表里的cookie_name对应的value

cookie_name_u:表示用户的ID,对应USERS_TABLE里的user_id

cookie_name_sid:会话ID,用户登录后作为当前站上唯一的值,来统计在线用户的当前操作、人数等,其对应值在phpbb_sessions表里

因为本人 的站点正好也有这两个cookie,但名称不一样,在本站上分别为:mysite_uid,对应用户表的id值,mysite_sid,对应的会话值,如 何使之统一?要么以phpb3为标准,要么以本站为标准,最后决定还是以本站为标准,所以将phpbb3里所有cookie_name_u替换为 myste_uid(修改session.php及auth.php文件),所有的cookie_name_sid替换为mysite_sid(修改 phpbb_config表里的cookie_name的value字段为mysite即可)

好了,现在cookie一至了。

2、用户登录:
phpbb用户登录的登录大概流程是这样的:

      1 <?php
      2 define('IN_PHPBB', true);
      3 $phpbb_root_path = './';
      4 $phpEx = substr(strrchr(__FILE__, '.'), 1);
      5 include($phpbb_root_path . 'common.' . $phpEx);
      6 
      7 // Start session management
      8 $user->session_begin();
      9 $auth->acl($user->data);
     10 $user->setup();
     11 if($user->data['is_registered'])
     12 {
     13     echo "User is already logged in to phpBB";
     14 }
     15 else
     16 {
     17     $username = request_var('username', '', true);
     18     $password = request_var('password', '', true);
     19     $autologin = (!empty($_POST['autologin'])) ? true : false;
     20     $result = $auth->login($username, $password, $autologin);
     21 
     22     if ($result['status'] == LOGIN_SUCCESS)
     23     {
     24         echo "User was successfully logged into phpBB";
     25     }
     26     else
     27     {
     28         echo "User's login failed";
     29 
     30     }
     31 }
     32 
     33 //Start login verification code for main site
     34 ?>
     35 <form action="./mylogin.php" method="post" id="login">
     36 <div class="panel">
     37     <div class="inner"><span class="corners-top"><span></span></span>
     38         <div class="content">
     39             <h2>登录</h2>
     40             <fieldset class="fields1">
     41                     <dl>
     42                         <dt><label for="username">用户名:</label></dt>
     43                         <dd><input type="text" tabindex="1" name="username" id="username" size="25" value="" class="inputbox autowidth        " /></dd>
     44                     </dl>
     45                     <dl>
     46                         <dt><label for="password">密码:</label></dt>
     47                         <dd><input type="password" tabindex="2" id="password" name="password" size="25" class="inputbox autowidth" /><        /dd>
     48                         <dd><a href="http://yourdomain.com/blog/./ucp.php?mode=sendpassword">我忘记了自己的密码</a></dd& gt;       </dl>
     49                     <dl>
     50                         <dd><label for="autologin"><input type="checkbox" name="autologin" id="autologin" tabindex="4" /> 每次浏览时自
        动登录</label></dd>           <dd><label for="viewonline"><input type="checkbox" name="viewonline" id="viewonline" tabindex="5" /> 在>        这次登录中隐藏我的在线状态</label></dd>
     51                         </dl>
     52                         <dl>
     53                             <dt>&nbsp;</dt>
     54                             <dd><input type="hidden" name="redirect" value="index.php" />
     55                             
     56                             <input type="submit" name="login" tabindex="6" value="登录" class="button1" /></dd>
     57                         </dl>
     58             </fieldset>
     59         </div>
     60         <span class="corners-bottom"><span></span></span>
     61     </div>
     62 </div>
     63 <div class="panel">
     64     <div class="inner"><span class="corners-top"><span></span></span>
     65             <div class="content">
     66                 <h3>注册</h3>
     67                 <p>您必须注册后才能登录。注册仅需要很短的时间但是会给您更多的权限。在注册前请确认您已经明白我们的使用条款和政策。当?览
        论坛时请确认您已经阅读过版面规则。</p>
     68                 <p><strong><a href="http://yourdomain.com/blog/./ucp.php?mode=terms">使用条款</a> | <a href="http://yourdomain.com/./ucp.php?mode=privacy">隐私政策</a></strong></p>
     69                 <hr class="dashed" />
     70                 <p><a href="http://yourdomain.com/./ucp.php?mode=register" class="button2">注册</a></p>
     71             </div>
     72             <span class="corners-bottom"><span></span></span>
     73     </div>
     74 </div>
     75 </form>
将其复制并保存在phpbb3目录下,并命名为mylogin.php,然后起交用户名密码,就可以看到登录成功了,登录程序会根据提交的 用户名去读取phpbb_users表,然后根据提交的密码做hash,和用户表里的密码做对比,如果一至,则登录成功,启动刚才所说的两个 cookie,否则不成功,任为匿名用户的sid。

phpbb3里对用户密码除了用md5外,还做了进一步的hash,所以如果你的站点用户表里的密码如果是用md5加密的,生搬硬套过来后以前的用户恳定无法登录,怎么办?

在include/functions.php文件里有个 phpbb_check_hash($password,$hash),它就是负责对密码 进行检查的,将该函数里的代码注掉,并把最后一句改为:return (md5($password) === $hash) ? true : false;,如下:

    326 function phpbb_check_hash($password, $hash)
    327 {
    328     
    329     /*
    330     $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    331     if (strlen($hash) == 34)
    332     {
    333         return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
    334     }
    335     */
    336     return (md5($password) === $hash) ? true : false;
    337 }   
这样就避过了phpbb3的hash加密,仍用本站原来的md5进行加密,这样本站以前的老用户在phpbb论坛下一样可以登录。

3、用户注册

登录做好了,可是如果用户在phpbb3下注册了新用户(注意注册程序仍使用phpbb3自带的hash加密方法),由于注册程序用hash方法加密,而登录程序用md5方法加密,恳定还会有问题。怎么办?

好说的很,同样在include/functions.php文件里修改如下函数:

   285 function phpbb_hash($password) 
    286 {
    287     /*
    288     $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
    289     
    290     $random_state = unique_id();
    291     $random = '';
    292     $count = 6;
    293             
    294     if (($fh = @fopen('/dev/urandom', 'rb')))
    295     {
    296         $random = fread($fh, $count);
    297         fclose($fh);
    298     }
    299     
    300     if (strlen($random) < $count)
    301     {       
    302         $random = '';
    303     
    304         for ($i = 0; $i < $count; $i += 16)
    305         {
    306             $random_state = md5(unique_id() . $random_state);
    307             $random .= pack('H*', md5($random_state));
    308         }
    309         $random = substr($random, 0, $count);
    310     }
    311 
    312     $hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64);
    313 
    314     if (strlen($hash) == 34)
    315     {
    316         return $hash;
    317     }
    318     */
    319 
    320     return md5($password);
    321 }
这样注册程序也避开了hash加密方法,而采用md5了,这样就不会再有密码错误的提示

4、合并表格:

根据各自的站点用户表看情况,将两个user表合二为一,做并集,然后修改程序中使用到的相应表名即可。

总结:

其实集成的方法多种多样,因人而异,至于用户password采用phpbb3的hash方法好还是采用md5好,本人认为当然是phpbb3的hash方法好,更安全,但因为本站的用户太多,如果采用此法,那么所有的老用户都将无法登录,所以就采用md5了。

另附phpbb3的注册程序,可能有人使用其它方法集成时会用到:

      1 <?php
      2     define('IN_PHPBB',true);
      3     $phpbb_root_path = "./";
      4     $phpEx = substr(strrchr(__FILE__, '.'), 1);
      5     require_once( $phpbb_root_path . "common." . $phpEx );
      6     include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
      7     include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
      8 
      9     // Start session management
     10     $user->session_begin();
     11     $auth->acl($user->data);
     12     $user->setup('ucp');
     13 
     14     if($user->data['is_registered'])
     15     {
     16             meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx"));
     17             trigger_error("You are already registered!");
     18     }
     19 
     20     $submit = request_var('submit', '');
     21     if($submit)
     22     {
     23             // Retrieve default group ID
     24             $sql = 'SELECT group_id
     25                     FROM ' . GROUPS_TABLE . "
     26                     WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
     27                             AND group_type = " . GROUP_SPECIAL;
     28             $result = $db->sql_query($sql);
     29             $row = $db->sql_fetchrow($result);
     30             $db->sql_freeresult($result);
     31 
     32             if (!$row)
     33             {
     34                     trigger_error('NO_GROUP');
     35             }
     36             $group_id = $row['group_id'];
     37 
     38 
     39             $data = array(
     40                     'username'                      => utf8_normalize_nfc(request_var('username', '', true)),
     41                     'user_password'         => phpbb_hash(request_var('password', '', true)),
     42                     'user_email'            => strtolower(request_var('email', '')),
     43                     'group_id'                      => (int) $group_id,
     44                     'user_type'                     => USER_NORMAL,
     45                     'user_ip'                       => $user->ip,
     46             );
     47 
     48             $user_id = user_add($data);
     49 
     50             if ($user_id === false)
     51             {
     52                     trigger_error('NO_USER', E_USER_ERROR);
     53             }
     54 
     55             //Set up welcome message
     56             if ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable'])
     57             {
     58                     $message = $user->lang['ACCOUNT_INACTIVE'];
     59             }
     60             else if ($config['require_activation'] == USER_ACTIVATION_ADMIN && $config['email_enable'])
     61             {
     62                     $message = $user->lang['ACCOUNT_INACTIVE_ADMIN'];
     63             }
     64             else
     65             {
     66                     $message = $user->lang['ACCOUNT_ADDED'];
     67             }
     68 
     69             //Display message
     70             $message = $message . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="http://yourdomain.com/' . append_sid("{$phpbb_root_path}in        dex.$phpEx") . '">', '</a>');
     71             trigger_error($message);
     72     }
     73     else
     74     {
     75             echo '<form action="./test.php" method="post">
     76                             Username: <input type="text" name="username" /><br />
     77                             E-mail address: <input type="text" name="email" size="25" maxlength="100" /><br />
     78                             Password: <input type="password" name="password" size="25" /><br />
     79                             <input type="submit" name="submit" value="Submit" />
     80                             </form>';
     81     }
     82 ?>