php摘要認證(digest)
在 firefox 中 或 ie瀏覽器
中都能夠正常彈出認證視窗,但是在 chrome核心的瀏覽器(例如:360安全瀏覽器)
中無法彈出認證視窗(廣告過濾外掛程式等已經關掉了)。
PHP 代碼: $realm = 'ftl.com'; $qop = 'auth'; $nonce = md5(time()); header('WWW-Authenticate: Digest realm=' . $realm . ' qop=' . $qop . ' nonce=' . $nonce); header('HTTP/1.1 401 Unauthorized'); echo '你取消了驗證!'; exit;
上面這段代碼在 360安全瀏覽器中
顯示:
查看頭部資訊:
在 Request Headers
中沒有 Authorization 頭的相關資訊。
然而在 firefox
中同一段代碼的顯示介面如下:
驗證成功後查看頭部資訊如下:
在要求標頭中也有 Authorization
頭。
怎樣在 chrome 核心的瀏覽器中完成 digest 認證(PHP 官網教程的代碼在也會出現這個問題)??
最後,貼出完整的測試代碼:
Javscript
部分:
var url = 'php/xhr.php';var xhr = new XMLHttpRequest();xhr.open('post' , url , true , 'test' , '123456');xhr.setRequestHeader('Content-Type' , 'Application/x-www-form-urlencoded');xhr.send(null);xhr.onload = function(){ console.log('服務端反饋會資料:' , this.response);}
PHP
部分:
$users = array('test' => '123456');if (!isset($_SERVER['PHP_AUTH_DIGEST'])) { authenticate(); exit;}$digest = explode(',' , trim_all($_SERVER['PHP_AUTH_DIGEST'] , true));$rel = array();array_walk($digest , function($val){ global $rel; $arr = explode('=' , $val); $rel[$arr[0]] = $arr[1]; unset($arr);});unset($digest);// 安全部分$secure_part = $rel['username'] . ':' . $rel['realm'] . ':' . $users[$rel['username']];// 報文部分$header_part = $_SERVER['REQUEST_METHOD'] . ':' . $rel['uri'];// 摘要計算$response = md5($secure_part) . ':' . $rel['nonce'] . ':' . $rel['nc'] . ':' . $rel['cnonce'] . ':' . $rel['qop'] . ':' . md5($header_part);$response = md5($response);// 驗證if ($rel['response'] === $response) { echo '驗證成功!';} else { //authenticate(); echo '驗證失敗!';}// 認證函數function authenticate(){ $realm = 'ftl.com'; $qop = 'auth'; $nonce = md5(time()); header('WWW-Authenticate: Digest realm=' . $realm . ' qop=' . $qop . ' nonce=' . $nonce); header('HTTP/1.1 401 Unauthorized'); echo '你取消了驗證!'; exit;}/* * 過濾 * 基本過濾:空格 \r \n 字串 * 加強過濾:單引號 雙引號 */function trim_all($str = '' , $isStripQuote = false){ $str = preg_replace('/^( |\r|\n)+/' , '' , $str); $str = preg_replace('/( |\r|\n)+$/' , '' , $str); $str = preg_replace('/(\W)( |\r|\n)+/' , '$1' , $str); $str = preg_replace('/( |\r|\n)+(\W)/' , '$2' , $str); if ($isStripQuote) { $str = preg_replace('/"|\'/' , '' , $str); } return $str;}
回複內容:
php摘要認證(digest)
在 firefox 中 或 ie瀏覽器
中都能夠正常彈出認證視窗,但是在 chrome核心的瀏覽器(例如:360安全瀏覽器)
中無法彈出認證視窗(廣告過濾外掛程式等已經關掉了)。
PHP 代碼: $realm = 'ftl.com'; $qop = 'auth'; $nonce = md5(time()); header('WWW-Authenticate: Digest realm=' . $realm . ' qop=' . $qop . ' nonce=' . $nonce); header('HTTP/1.1 401 Unauthorized'); echo '你取消了驗證!'; exit;
上面這段代碼在 360安全瀏覽器中
顯示:
查看頭部資訊:
在 Request Headers
中沒有 Authorization 頭的相關資訊。
然而在 firefox
中同一段代碼的顯示介面如下:
驗證成功後查看頭部資訊如下:
在要求標頭中也有 Authorization
頭。
怎樣在 chrome 核心的瀏覽器中完成 digest 認證(PHP 官網教程的代碼在也會出現這個問題)??
最後,貼出完整的測試代碼:
Javscript
部分:
var url = 'php/xhr.php';var xhr = new XMLHttpRequest();xhr.open('post' , url , true , 'test' , '123456');xhr.setRequestHeader('Content-Type' , 'Application/x-www-form-urlencoded');xhr.send(null);xhr.onload = function(){ console.log('服務端反饋會資料:' , this.response);}
PHP
部分:
$users = array('test' => '123456');if (!isset($_SERVER['PHP_AUTH_DIGEST'])) { authenticate(); exit;}$digest = explode(',' , trim_all($_SERVER['PHP_AUTH_DIGEST'] , true));$rel = array();array_walk($digest , function($val){ global $rel; $arr = explode('=' , $val); $rel[$arr[0]] = $arr[1]; unset($arr);});unset($digest);// 安全部分$secure_part = $rel['username'] . ':' . $rel['realm'] . ':' . $users[$rel['username']];// 報文部分$header_part = $_SERVER['REQUEST_METHOD'] . ':' . $rel['uri'];// 摘要計算$response = md5($secure_part) . ':' . $rel['nonce'] . ':' . $rel['nc'] . ':' . $rel['cnonce'] . ':' . $rel['qop'] . ':' . md5($header_part);$response = md5($response);// 驗證if ($rel['response'] === $response) { echo '驗證成功!';} else { //authenticate(); echo '驗證失敗!';}// 認證函數function authenticate(){ $realm = 'ftl.com'; $qop = 'auth'; $nonce = md5(time()); header('WWW-Authenticate: Digest realm=' . $realm . ' qop=' . $qop . ' nonce=' . $nonce); header('HTTP/1.1 401 Unauthorized'); echo '你取消了驗證!'; exit;}/* * 過濾 * 基本過濾:空格 \r \n 字串 * 加強過濾:單引號 雙引號 */function trim_all($str = '' , $isStripQuote = false){ $str = preg_replace('/^( |\r|\n)+/' , '' , $str); $str = preg_replace('/( |\r|\n)+$/' , '' , $str); $str = preg_replace('/(\W)( |\r|\n)+/' , '$1' , $str); $str = preg_replace('/( |\r|\n)+(\W)/' , '$2' , $str); if ($isStripQuote) { $str = preg_replace('/"|\'/' , '' , $str); } return $str;}