PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/lithium/libraries/lithium/security/auth/adapter/Http.php

https://github.com/brtriver/sukonv
PHP | 155 lines | 61 code | 17 blank | 77 comment | 4 complexity | 299e9079ce674adeaaab7f922ec6315d MD5 | raw file
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2010, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\security\auth\adapter;
  9. use lithium\core\Libraries;
  10. /**
  11. * The `Http` adapter provides basic and digest authentication based on the HTTP protocol.
  12. * By default, the adapter uses Http Digest based authentication.
  13. * {{{
  14. * Auth::config(array('name' => array('adapter' => 'Http', 'users' => array('gwoo' => 'li3'))))
  15. * }}}
  16. *
  17. * To use Basic authentication, set the `method` to basic.
  18. * {{{
  19. * Auth::config(array('name' => array(
  20. * 'adapter' => 'Http', 'users' => array('gwoo' => 'li3'),
  21. * 'method' => 'basic'
  22. * )))
  23. * }}}
  24. *
  25. * @link http://tools.ietf.org/html/rfc2068#section-14.8
  26. * @see `\lithium\action\Request`
  27. */
  28. class Http extends \lithium\core\Object {
  29. /**
  30. * Setup default configuration options.
  31. *
  32. * @param array $config
  33. * - `method`: default: `digest` options: `basic|digest`
  34. * - `realm`: default: `Protected by Lithium`
  35. * - `users`: the users to permit. key => value pair of username => password
  36. */
  37. public function __construct(array $config = array()) {
  38. $defaults = array(
  39. 'method' => 'digest', 'realm' => basename(LITHIUM_APP_PATH), 'users' => array()
  40. );
  41. parent::__construct($config + $defaults);
  42. }
  43. /**
  44. * Called by the `Auth` class to run an authentication check against the HTTP data using the
  45. * credientials in a data container (a `Request` object), and returns an array of user
  46. * information on success, or `false` on failure.
  47. *
  48. * @param object $request A env container which wraps the authentication credentials used
  49. * by HTTP (usually a `Request` object). See the documentation for this
  50. * class for further details.
  51. * @param array $options Additional configuration options. Not currently implemented in this
  52. * adapter.
  53. * @return array Returns an array containing user information on success, or `false` on failure.
  54. */
  55. public function check($request, array $options = array()) {
  56. $method = "_{$this->_config['method']}";
  57. return $this->{$method}($request);
  58. }
  59. /**
  60. * A pass-through method called by `Auth`. Returns the value of `$data`, which is written to
  61. * a user's session. When implementing a custom adapter, this method may be used to modify or
  62. * reject data before it is written to the session.
  63. *
  64. * @param array $data User data to be written to the session.
  65. * @param array $options Adapter-specific options. Not implemented in the `Form` adapter.
  66. * @return array Returns the value of `$data`.
  67. */
  68. public function set($data, array $options = array()) {
  69. return $data;
  70. }
  71. /**
  72. * Called by `Auth` when a user session is terminated. Not implemented in the `Form` adapter.
  73. *
  74. * @param array $options Adapter-specific options. Not implemented in the `Form` adapter.
  75. * @return void
  76. */
  77. public function clear(array $options = array()) {
  78. }
  79. /**
  80. * Handler for HTTP Basic Authentication
  81. *
  82. * @param string $request a `\lithium\action\Request` object
  83. * @return void
  84. */
  85. protected function _basic($request) {
  86. $users = $this->_config['users'];
  87. $username = $request->env('PHP_AUTH_USER');
  88. $password = $request->env('PHP_AUTH_PW');
  89. if (!isset($users[$username]) || $users[$username] !== $password) {
  90. $this->_writeHeader("WWW-Authenticate: Basic realm=\"{$this->_config['realm']}\"");
  91. return;
  92. }
  93. return compact('username', 'password');
  94. }
  95. /**
  96. * Handler for HTTP Digest Authentication
  97. *
  98. * @param string $request a `\lithium\action\Request` object
  99. * @return void
  100. */
  101. protected function _digest($request) {
  102. $realm = $this->_config['realm'];
  103. $data = array(
  104. 'username' => null, 'nonce' => null, 'nc' => null,
  105. 'cnonce' => null, 'qop' => null, 'uri' => null,
  106. 'response' => null
  107. );
  108. $result = array_map(function ($string) use (&$data) {
  109. $parts = explode('=', trim($string), 2) + array('', '');
  110. $data[$parts[0]] = trim($parts[1], '"');
  111. }, explode(',', $request->env('PHP_AUTH_DIGEST')));
  112. $users = $this->_config['users'];
  113. $password = !empty($users[$data['username']]) ? $users[$data['username']] : null;
  114. $user = md5("{$data['username']}:{$realm}:{$password}");
  115. $nonce = "{$data['nonce']}:{$data['nc']}:{$data['cnonce']}:{$data['qop']}";
  116. $req = md5($request->env('REQUEST_METHOD') . ':' . $data['uri']);
  117. $hash = md5("{$user}:{$nonce}:{$req}");
  118. if (!$data['username'] || $hash !== $data['response']) {
  119. $nonce = uniqid();
  120. $opaque = md5($realm);
  121. $message = "WWW-Authenticate: Digest realm=\"{$realm}\" qop=\"auth\",";
  122. $message .= "nonce=\"{$nonce}\",opaque=\"{$opaque}\"";
  123. $this->_writeHeader($message);
  124. return;
  125. }
  126. return array('username' => $data['username'], 'password' => $password);
  127. }
  128. /**
  129. * Helper method for writing headers. Mainly used to override the output while testing.
  130. *
  131. * @param string $string the string the send as a header
  132. * @return void
  133. */
  134. protected function _writeHeader($string) {
  135. header($string, true);
  136. }
  137. }
  138. ?>