forked from UnionOfRAD/lithium
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added the
net\http\Auth
class and refactored net\http\Request
and…
… `security\auth\adapter\Http` to use it.
- Loading branch information
Showing
9 changed files
with
262 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
<?php | ||
/** | ||
* Lithium: the most rad php framework | ||
* | ||
* @copyright Copyright 2012, Union of RAD (http://union-of-rad.org) | ||
* @license http://opensource.org/licenses/bsd-license.php The BSD License | ||
*/ | ||
|
||
namespace lithium\net\http; | ||
|
||
/** | ||
* The `Auth` class handles HTTP Authentication encoding and decode. Typically, this class is not | ||
* used directly, but is a utility of `action\Request` and `security\auth\adapter\Http` | ||
*/ | ||
class Auth extends \lithium\core\StaticObject { | ||
|
||
/** | ||
* The NC value needed for digest authentication | ||
* | ||
*/ | ||
public static $nc = '00000001'; | ||
|
||
/** | ||
* Returns the proper header string. Accepts the data from the `encode` method. | ||
* | ||
* @param array $data | ||
* @return string | ||
*/ | ||
public static function header($data) { | ||
if (empty($data['response'])) { | ||
return null; | ||
} | ||
if (!empty($data['opaque'])) { | ||
$defaults = array( | ||
'realm' => 'app', 'method' => 'GET', 'uri' => '/', | ||
'username' => null, 'qop' => 'auth', | ||
'nonce' => null, 'opaque' => null, | ||
'cnonce' => md5(time()), 'nc' => static::$nc | ||
); | ||
$data += $defaults; | ||
$auth = "username=\"{$data['username']}\", response=\"{$data['response']}\", "; | ||
$auth .= "uri=\"{$data['uri']}\", realm=\"{$data['realm']}\", "; | ||
$auth .= "qop=\"{$data['qop']}\", nc={$data['nc']}, cnonce=\"{$data['cnonce']}\", "; | ||
$auth .= "nonce=\"{$data['nonce']}\", opaque=\"{$data['opaque']}\""; | ||
return "Digest " . $auth; | ||
} | ||
return "Basic " . $data['response']; | ||
} | ||
|
||
/** | ||
* Encoded the data with username and password to create the proper response. Returns an array | ||
* containing the username and encoded response. | ||
* | ||
* @param string $username Username to authenticate with | ||
* @param string $password Password to authenticate with | ||
* @param array $data Params needed to hash the response | ||
* @return array | ||
*/ | ||
public static function encode($username, $password, $data = array()) { | ||
if (isset($data['nonce'])) { | ||
$defaults = array( | ||
'realm' => 'app', 'method' => 'GET', 'uri' => '/', 'qop' => null, | ||
'cnonce' => md5(time()), 'nc' => static::$nc | ||
); | ||
$data = array_filter($data) + $defaults; | ||
$part1 = md5("{$username}:{$data['realm']}:{$password}"); | ||
$part2 = "{$data['nonce']}:{$data['nc']}:{$data['cnonce']}:{$data['qop']}"; | ||
$part3 = md5($data['method'] . ':' . $data['uri']); | ||
$response = md5("{$part1}:{$part2}:{$part3}"); | ||
return compact('username', 'response') + $data; | ||
} | ||
$response = base64_encode("{$username}:{$password}"); | ||
return compact('username', 'response'); | ||
} | ||
|
||
/** | ||
* Takes the header string and parses out the params needed for a digest authentication. | ||
* | ||
* @param string $header | ||
* @return array | ||
*/ | ||
public static function decode($header) { | ||
$data = array( | ||
'realm' => null, 'username' => null, 'uri' => null, | ||
'nonce' => null, 'opaque' => null, 'qop' => null, | ||
'cnonce' => null, 'nc' => null, | ||
'response' => null | ||
); | ||
$keys = implode('|', array_keys($data)); | ||
$regex = '@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@'; | ||
preg_match_all($regex, $header, $matches, PREG_SET_ORDER); | ||
|
||
foreach ($matches as $m) { | ||
if (!isset($m[3]) && !isset($m[4])) { | ||
continue; | ||
} | ||
$data[$m[1]] = $m[3] ? $m[3] : $m[4]; | ||
} | ||
return $data; | ||
} | ||
} | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
<?php | ||
/** | ||
* Lithium: the most rad php framework | ||
* | ||
* @copyright Copyright 2012, Union of RAD (http://union-of-rad.org) | ||
* @license http://opensource.org/licenses/bsd-license.php The BSD License | ||
*/ | ||
|
||
namespace lithium\tests\cases\net\http; | ||
|
||
use lithium\net\http\Auth; | ||
|
||
class AuthTest extends \lithium\test\Unit { | ||
|
||
public function testBasicEncode() { | ||
$username = 'gwoo'; | ||
$password = 'li3'; | ||
$response = base64_encode("{$username}:{$password}"); | ||
$expected = compact('username', 'response'); | ||
$result = Auth::encode($username, $password); | ||
$this->assertEqual($expected, $result); | ||
} | ||
|
||
|
||
public function testDigestEncode() { | ||
$username = 'gwoo'; | ||
$password = 'li3'; | ||
$nc = '00000001'; | ||
$cnonce = md5(time()); | ||
$user = md5("gwoo:app:li3"); | ||
$nonce = "4bca0fbca7bd0:{$nc}:{$cnonce}:auth"; | ||
$req = md5("GET:/http_auth"); | ||
$response = md5("{$user}:{$nonce}:{$req}"); | ||
|
||
$data = array( | ||
'realm' => 'app', | ||
'method' => 'GET', | ||
'uri' => '/http_auth', | ||
'qop' => 'auth', | ||
'nonce' => '4bca0fbca7bd0', | ||
'opaque' => 'd3fb67a7aa4d887ec4bf83040a820a46' | ||
); | ||
$expected = $data + compact('username', 'response', 'nc', 'cnonce'); | ||
$result = Auth::encode($username, $password, $data); | ||
$this->assertEqual($expected, $result); | ||
} | ||
|
||
public function testBasicHeader() { | ||
$username = 'gwoo'; | ||
$password = 'li3'; | ||
$response = base64_encode("{$username}:{$password}"); | ||
$data = Auth::encode($username, $password); | ||
$expected = "Basic " . $response; | ||
$result = Auth::header($data); | ||
$this->assertEqual($expected, $result); | ||
} | ||
|
||
public function testDigestHeader() { | ||
$username = 'gwoo'; | ||
$password = 'li3'; | ||
$nc = '00000001'; | ||
$cnonce = md5(time()); | ||
$user = md5("gwoo:app:li3"); | ||
$nonce = "4bca0fbca7bd0:{$nc}:{$cnonce}:auth"; | ||
$req = md5("GET:/http_auth"); | ||
$hash = md5("{$user}:{$nonce}:{$req}"); | ||
|
||
$data = array( | ||
'realm' => 'app', | ||
'method' => 'GET', | ||
'uri' => '/http_auth', | ||
'qop' => 'auth', | ||
'nonce' => '4bca0fbca7bd0', | ||
'opaque' => 'd3fb67a7aa4d887ec4bf83040a820a46' | ||
); | ||
$data = Auth::encode($username, $password, $data); | ||
$header = Auth::header($data); | ||
$this->assertPattern('/Digest/', $header); | ||
preg_match('/response="(.*?)"/', $header, $matches); | ||
list($match, $response) = $matches; | ||
|
||
$expected = $hash; | ||
$result = $response; | ||
$this->assertEqual($expected, $result); | ||
} | ||
|
||
public function testDecode() { | ||
$header = 'qop="auth",nonce="4bca0fbca7bd0",' | ||
. 'nc="00000001",cnonce="95b2cd1e179bf5414e52ed62811481cf",' | ||
. 'uri="/http_auth",realm="app",' | ||
. 'opaque="d3fb67a7aa4d887ec4bf83040a820a46",username="gwoo",' | ||
. 'response="04d7d878c67f289f37e553d2025e3a52"'; | ||
|
||
$expected = array( | ||
'qop' => 'auth', 'nonce' => '4bca0fbca7bd0', | ||
'nc' => '00000001', 'cnonce' => '95b2cd1e179bf5414e52ed62811481cf', | ||
'uri' => '/http_auth', 'realm' => 'app', | ||
'opaque' => 'd3fb67a7aa4d887ec4bf83040a820a46', 'username' => 'gwoo', | ||
'response' => '04d7d878c67f289f37e553d2025e3a52' | ||
); | ||
$result = Auth::decode($header); | ||
$this->assertEqual($expected, $result); | ||
} | ||
} | ||
|
||
?> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters