forked from UnionOfRAD/lithium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Http.php
171 lines (156 loc) · 5.59 KB
/
Http.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
/**
* Lithium: the most rad php framework
*
* @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
* @license http://opensource.org/licenses/bsd-license.php The BSD License
*/
namespace lithium\security\auth\adapter;
use lithium\core\Libraries;
/**
* The `Http` adapter provides basic and digest authentication based on the HTTP protocol.
* By default, the adapter uses Http Digest based authentication.
* {{{
* Auth::config(array('name' => array('adapter' => 'Http', 'users' => array('gwoo' => 'li3'))))
* }}}
*
* To use Basic authentication, set the `method` to basic.
* {{{
* Auth::config(array('name' => array(
* 'adapter' => 'Http', 'users' => array('gwoo' => 'li3'),
* 'method' => 'basic'
* )))
* }}}
*
* When running PHP as a CGI/FCGI PHP doesn't automatically parse the authorization
* header into `PHP_AUTH_*` headers. Lithium will work arround this issue by looking for
* a `HTTP_AUTHORIZATION` header instead. When using PHP as a CGI/FCGI in combination
* with Apache you must additionally add the following rewrite rule to your configuration
* in order to make the header available so Lithium can pick it up:
* {{{
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
* }}}
*
* @link http://tools.ietf.org/html/rfc2068#section-14.8
* @see lithium\action\Request
* @see lithium\action\Request::env
*/
class Http extends \lithium\core\Object {
/**
* Dynamic class dependencies.
*
* @var array Associative array of class names & their namespaces.
*/
protected $_classes = array(
'auth' => 'lithium\net\http\Auth'
);
/**
* Setup default configuration options.
*
* @param array $config
* - `method`: default: `digest` options: `basic|digest`
* - `realm`: default: `Protected by Lithium`
* - `users`: the users to permit. key => value pair of username => password
*/
public function __construct(array $config = array()) {
$realm = basename(Libraries::get(true, 'path'));
$defaults = array(
'method' => 'digest', 'realm' => $realm, 'users' => array()
);
parent::__construct($config + $defaults);
}
/**
* Called by the `Auth` class to run an authentication check against the HTTP data using the
* credentials in a data container (a `Request` object), and returns an array of user
* information on success, or `false` on failure.
*
* @param object $request A env container which wraps the authentication credentials used
* by HTTP (usually a `Request` object). See the documentation for this
* class for further details.
* @param array $options Additional configuration options. Not currently implemented in this
* adapter.
* @return array Returns an array containing user information on success, or `false` on failure.
*/
public function check($request, array $options = array()) {
$method = "_{$this->_config['method']}";
return $this->{$method}($request);
}
/**
* A pass-through method called by `Auth`. Returns the value of `$data`, which is written to
* a user's session. When implementing a custom adapter, this method may be used to modify or
* reject data before it is written to the session.
*
* @param array $data User data to be written to the session.
* @param array $options Adapter-specific options. Not implemented in the `Form` adapter.
* @return array Returns the value of `$data`.
*/
public function set($data, array $options = array()) {
return $data;
}
/**
* Called by `Auth` when a user session is terminated. Not implemented in the `Form` adapter.
*
* @param array $options Adapter-specific options. Not implemented in the `Form` adapter.
* @return void
*/
public function clear(array $options = array()) {}
/**
* Handler for HTTP Basic Authentication
*
* @param string $request a `\lithium\action\Request` object
* @return void
*/
protected function _basic($request) {
$users = $this->_config['users'];
$username = $request->env('PHP_AUTH_USER');
$auth = $this->_classes['auth'];
$basic = $auth::encode($username, $request->env('PHP_AUTH_PW'));
$encoded = array('response' => null);
if (isset($users[$username])) {
$encoded = $auth::encode($username, $users[$username]);
}
if ($basic['response'] !== $encoded['response']) {
$this->_writeHeader("WWW-Authenticate: Basic realm=\"{$this->_config['realm']}\"");
return;
}
return compact('username', 'password');
}
/**
* Handler for HTTP Digest Authentication
*
* @param string $request a `\lithium\action\Request` object
* @return void
*/
protected function _digest($request) {
$username = $password = null;
$auth = $this->_classes['auth'];
$data = $auth::decode($request->env('PHP_AUTH_DIGEST'));
$data['realm'] = $this->_config['realm'];
$data['method'] = $request->method;
$users = $this->_config['users'];
if (!empty($data['username']) && !empty($users[$data['username']])) {
$username = $data['username'];
$password = $users[$data['username']];
}
$encoded = $auth::encode($username, $password, $data);
if ($encoded['response'] !== $data['response']) {
$nonce = uniqid();
$opaque = md5($data['realm']);
$message = "WWW-Authenticate: Digest realm=\"{$data['realm']}\",qop=\"auth\",";
$message .= "nonce=\"{$nonce}\",opaque=\"{$opaque}\"";
$this->_writeHeader($message);
return false;
}
return compact('username', 'password');
}
/**
* Helper method for writing headers. Mainly used to override the output while testing.
*
* @param string $string the string the send as a header
* @return void
*/
protected function _writeHeader($string) {
header($string, true);
}
}
?>