未登录情形,访问dokuwiki(简称wiki),会自动分配一个生存期为session的cookie值。
这个名为DokuWiki的Cookie值由以下代码分配。
// init session if (!headers_sent() && !defined('NOSESSION')){ session_name("DokuWiki"); if (version_compare(PHP_VERSION, '5.2.0', '>')) { session_set_cookie_params(0,DOKU_REL,'',($conf['securecookie'] && is_ssl()),true); }else{ session_set_cookie_params(0,DOKU_REL,'',($conf['securecookie'] && is_ssl())); } session_start(); // load left over messages if(isset($_SESSION[DOKU_COOKIE]['msg'])){ $MSG = $_SESSION[DOKU_COOKIE]['msg']; unset($_SESSION[DOKU_COOKIE]['msg']); } }
输入用户名和密码后具体登陆过程在
/** * This tries to login the user based on the sent auth credentials * * The authentication works like this: if a username was given * a new login is assumed and user/password are checked. If they * are correct the password is encrypted with blowfish and stored * together with the username in a cookie - the same info is stored * in the session, too. Additonally a browserID is stored in the * session. * * If no username was given the cookie is checked: if the username, * crypted password and browserID match between session and cookie * no further testing is done and the user is accepted * * If a cookie was found but no session info was availabe the * blowfish encrypted password from the cookie is decrypted and * together with username rechecked by calling this function again. * * On a successful login $_SERVER[REMOTE_USER] and $USERINFO * are set. * * @author Andreas Gohr <andi@splitbrain.org> * * @param string $user Username * @param string $pass Cleartext Password * @param bool $sticky Cookie should not expire * @param bool $silent Don't show error on bad auth * @return bool true on successful auth */ function auth_login($user,$pass,$sticky=false,$silent=false){ global $USERINFO; global $conf; global $lang; global $auth; $sticky ? $sticky = true : $sticky = false; //sanity check if (!$auth) return false; if(!empty($user)){ //usual login if ($auth->checkPass($user,$pass)){ // make logininfo globally available $_SERVER['REMOTE_USER'] = $user; auth_setCookie($user,PMA_blowfish_encrypt($pass,auth_cookiesalt()),$sticky); return true; }else{ //invalid credentials - log off if(!$silent) msg($lang['badlogin'],-1); auth_logoff(); return false; } }else{ // read cookie information list($user,$sticky,$pass) = auth_getCookie(); // get session info $session = $_SESSION[DOKU_COOKIE]['auth']; if($user && $pass){ // we got a cookie - see if we can trust it if(isset($session) && $auth->useSessionCache($user) && ($session['time'] >= time()-$conf['auth_security_timeout']) && ($session['user'] == $user) && ($session['pass'] == $pass) && //still crypted ($session['buid'] == auth_browseruid()) ){ // he has session, cookie and browser right - let him in $_SERVER['REMOTE_USER'] = $user; $USERINFO = $session['info']; //FIXME move all references to session return true; } // no we don't trust it yet - recheck pass but silent $pass = PMA_blowfish_decrypt($pass,auth_cookiesalt()); return auth_login($user,$pass,$sticky,true); } } //just to be sure auth_logoff(true); return false; }
验证成功后,由函数auth_setCookie()来写入Cookie信息
auth_setCookie($user,PMA_blowfish_encrypt($pass,auth_cookiesalt()),$sticky);
auth_setCookie()涉及加密,由PMA_blowfish_encrypt()来完成。
// higher-level functions: /** * Encryption using blowfish algorithm * * @param string original data * @param string the secret * * @return string the encrypted result * * @access public * * @author lem9 */ function PMA_blowfish_encrypt($data, $secret) { $pma_cipher = new Horde_Cipher_blowfish; $encrypt = ''; $data .= '_'; // triming fixed for DokuWiki FS#1690 FS#1713 $mod = strlen($data) % 8; if ($mod > 0) { $data .= str_repeat("\0", 8 - $mod); } foreach (str_split($data, 8) as $chunk) { $encrypt .= $pma_cipher->encryptBlock($chunk, $secret); } return base64_encode($encrypt); }
/** * cURL模拟wiki登陆,将cookie信息写入到用户浏览器 * * @param string $user_name 用户名,不可以是邮箱,只限用户名 * @param string $password 密码 * */ function my_wiki_login($user_name, $password) { global $_SCONFIG; //请求地址 $url = $_SCONFIG['wiki']['wikihost']."doku.php"; //参数 $params = "do=login&id=start&u=".urlencode($user_name)."&p=".urlencode($password); //cURL模拟请求登陆页面 $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); curl_setopt($ch, CURLOPT_HEADER, 1);//输出头部 curl_setopt($ch, CURLOPT_NOBODY, 1);//关闭BODY输出 curl_setopt($ch, CURLOPT_POST, 1);//post curl_setopt($ch, CURLOPT_POSTFIELDS, $params);//参数 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//返回请求输出 $res = curl_exec($ch);//do exec curl_close($ch); //获取Set-Cookie头部 $res_arr = explode("\r\n", $res); foreach( $res_arr as $head_line) { if( preg_match("/^set\-cookie\:/i", $head_line) ) { //$cookie_header_arr[] = $head_line; /* set http response header */ header($head_line, 0);//replace=false } } //return $cookie_header_arr; return true; }
上述代码首先找到set-cookie的头信息,然后再使用header()函数,写入即可。这样就可以一次登陆啦。