So I could only find one other PHP based HTTP digest auth example on the internet…and it looked as though it might not even work. I wrote an abstract class as a base that allows you to easily build your own implementation.
You’d use it like so:
class MyAuth extends HTTPDigestAuth { // Implementation of abstract methods } $authenticator = new MyAuth(); $user = $authenticator->authenticate(); if(!$user) { die(); }
The HTTPDigestAuth class looks like:
/* Copyright 2010 Alan Shaw http://freestyle-developments.co.uk Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Object orientated PHP HTTP digest authentication. * * Extend this class and implement abstract functions to create your own * HTTP digest authentication implementation. */ abstract class HTTPDigestAuth { //////////////////////////////////////////////////////////////////////// // @public /** * @return an authenticated user object on success, null otherwise. */ public function authenticate() { if(empty($_SERVER['PHP_AUTH_DIGEST'])) { $this->setHeadersUnauthorized(); $this->getResponseBodyUnauthorized(); return null; } $authClientData = new HTTPDigestAuthClientData($_SERVER['PHP_AUTH_DIGEST']); // Check for stale nonce if($this->isStaleNonce($authClientData->nonce)) { $this->setHeadersUnauthorized(true); $this->getResponseBodyUnauthorized(); return null; } // Check for correct nonce count if($authClientData->nc != $this->getNonceCount($authClientData->nonce) + 1) { $this->setHeadersBadRequest(); $this->getResponseBodyBadRequest('Incorrect nonce count'); return null; } $this->incrementNonceCount($authClientData->nonce); // Check request URI is the same as the auth digest uri if($authClientData->uri != $_SERVER['REQUEST_URI']) { $this->setHeadersBadRequest(); $this->getResponseBodyBadRequest('Digest auth URI != request URI'); return null; } // Check opaque is correct if($authClientData->opaque != $this->getOpaque()) { $this->setHeadersBadRequest(); $this->getResponseBodyBadRequest('Incorrect opaque'); return null; } // Check user exists if(!$this->userExists($authClientData->username)) { $this->setHeadersUnauthorized(); $this->getResponseBodyUnauthorized(); return null; } $ha1 = $this->getHA1ForUser($authClientData->username); // Generate A2 hash if($authClientData->qop == 'auth-int') { $a2 = $_SERVER['REQUEST_METHOD'] . ':' . stripslashes($_SERVER['REQUEST_URI']) . ':' . file_get_contents('php://input'); $ha2 = md5($a2); } else { $a2 = $_SERVER['REQUEST_METHOD'] . ':' . stripslashes($_SERVER['REQUEST_URI']); $ha2 = md5($a2); } // Generate the expected response if($authClientData->qop == 'auth' || $authClientData->qop == 'auth-int') { $expectedResponse = md5($ha1 . ':' . $authClientData->nonce . ':' . $authClientData->nc . ':' . $authClientData->cnonce . ':' . $authClientData->qop . ':' . $ha2); } else { $expectedResponse = md5($expectedResponse = $ha1 . ':' . $authClientData->nonce . ':' . $ha2); } // Check request contained the expected response if($authClientData->response != $expectedResponse) { $this->setHeadersBadRequest(); $this->getResponseBodyBadRequest(); return null; } return $this->getUser($authClientData->username); } //////////////////////////////////////////////////////////////////////// // @private private function setHeadersUnauthorized($stale = false) { header('HTTP/1.1 401 Unauthorized'); $authHeader = 'WWW-Authenticate: Digest realm="' . $this->getAuthRealm() . '",qop="auth-int,auth",algorithm="MD5",nonce="' . $this->createNonce() . '",opaque="' . $this->getOpaque() . '"'; if($stale) { $authHeader .= ',stale=TRUE'; } header($authHeader); } private static function setHeadersBadRequest() { header('HTTP/1.1 400 Bad Request'); } //////////////////////////////////////////////////////////////////////// // @optional protected function getResponseBodyUnauthorized($reason = '') { ?> <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Error</title> </head> <body> <h1>401 Unauthorized.</h1> <?php if($reason) { ?> <p><?php echo htmlspecialchars($reason); ?></p> <?php } ?> </body> </HTML> <?php } protected function getResponseBodyBadRequest($reason = '') { ?> <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Error</title> </head> <body> <h1>400 Bad Request.</h1> <?php if($reason) { ?> <p><?php echo htmlspecialchars($reason); ?></p> <?php } ?> </body> </HTML> <?php } //////////////////////////////////////////////////////////////////////// // @required /** * Gets the authentication realm for this class * * @return String */ abstract protected function getAuthRealm(); /** * Gets the opaque for this class * * @return String */ abstract protected function getOpaque(); /** * Creates a new nonce to send to the client * * @return String */ abstract protected function createNonce(); /** * Returns whether or not this nonce has expired. Should return true for * non existent nonce. * * @param String $nonce * @return Boolean */ abstract protected function isStaleNonce($nonce); /** * Gets the current request count for a particular nonce * * @param String $nonce The nonce to get the count of * @return uint The current nonce count */ abstract protected function getNonceCount($nonce); /** * Increments the nonce count by 1 * * @param String $nonce The nonce to increment */ abstract protected function incrementNonceCount($nonce); /** * Returns a boolean indicating whether or not a user with the specified * username exists. * * @param String $username * @return Boolean */ abstract protected function userExists($username); /** * Returns the A1 hash for the specified user. * i.e. return md5('username:realm:password') * * @param String $username * @return String */ abstract protected function getHA1ForUser($username); /** * Returns a user instance that belongs to the user with the username * provided. * * @param String $username * @return ??? */ abstract protected function getUser($username); } /** * @private */ class HTTPDigestAuthClientData { public $username; public $nonce; public $nc; public $cnonce; public $qop; public $uri; public $response; public $opaque; public function __construct($header) { preg_match_all('@(username|nonce|uri|nc|cnonce|qop|response|opaque)=[\'"]?([^\'",]+)@', $header, $t); $data = array_combine($t[1], $t[2]); $this->username = $data['username']; $this->nonce = $data['nonce']; $this->nc = $data['nc']; $this->cnonce = $data['cnonce']; $this->qop = $data['qop']; $this->uri = $data['uri']; $this->response = $data['response']; $this->opaque = $data['opaque']; } }
You can download the full source here: github.com/alanshaw/php-http-digest-auth
体構造のほとんどが生命戦維で構成されており、心臓を潰されても再生し、首を刎ねられても糸一本繋がっていれば体は機能する。洋一郎・清美の息子で大学生。鉄道ファンであり、同話では当時の上野駅に発着する鉄道の時刻表を手帳に記していた他、114巻「トロバス物語の巻」ではトロリーバスの操作もこなした。原作では両親と一緒に遊園地を遊び回る話が描かれたが、アニメ版では-ではなく+がこの役回りをしている。 アニメ版では父親と一緒に遊園地を回っていた際、ライバル企業の刺客に人質にされてしまう。
鳥羽洋典に聞く1(エキサイトレビュー)”. すしおに聞く2(エキサイトレビュー)”.
エキサイトニュース (2013年10月31日).
2014年7月1日閲覧。 エキサイトニュース (2013年10月17日).
2014年7月1日閲覧。 エキサイトニュース (2013年11月14日).
2014年7月1日閲覧。 MANTANWEB(まんたんウェブ) (2013年11月16日).
2014年7月1日閲覧。 アニメイトTV.
フロンティアワークス (2013年8月9日).
2013年10月17日閲覧。東大阪市で螺子工場を営む岩倉家の長女・
遺跡で検出された地震痕跡による古地震研究の成果 (PDF) 活断層・小松原純子、宍倉正展、岡村行信、「静岡県浮島ヶ原低地の水位上昇履歴と富士川河口断層帯の活動」 (PDF) 『活断層・
2020年5月2日閲覧。 2020年5月5日閲覧。 NHKニュース.
2020年4月30日閲覧。東海テレビ. 2020年4月9日閲覧。 1 May 2020.
2020年7月23日閲覧。 Young, Evan (31 January 2020).
“‘This is racism’: Chinese-Australians say they’ve faced increased hostility since the coronavirus outbreak began”.
Google Docs. 23 January 2020. 2020年1月27日閲覧。飯塚真紀子 (27
January 2020). “新型肺炎「武漢だけで、2月4日までに最大35万人超が感染」英米研究チーム”.
Villas-Boas, Antonio (19 March 2020). “インターネットのトラフィックが前年比2倍に…コロナウイルスによるリモートワークの増加が一因か”.
Patients seeking to manage Hepatitis C can find lasipen on the internet. This treatment option is accessible for those looking to minimize their healthcare expenses efficiently. Questioning where to obtain finasteride? Discover safe trustworthy options for best deals for finasteride . navigating the vast landscape of online pharmacies one often wonders https://mychik.com/prednisolone-prices/ . Whether you’re seeking to purchase this particular treatment securing a trustworthy provider is paramount. Keep your allergies at bay without leaving your home. Acquire your allergy relief medication through our website with ease. Visit prednisolone 5mg for your solution.