/
http-auth.xml
239 lines (214 loc) · 11.5 KB
/
http-auth.xml
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 2d1981cc3003cd94f5fb88e0473eed2c5b26efde Maintainer: shein Status: ready -->
<!-- Reviewed: no -->
<chapter xml:id="features.http-auth" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>HTTP-аутентификация в PHP</title>
<simpara>
Возможно использовать функцию <function>header</function> для
отправки сообщения <literal>"Authentication Required"</literal>
браузеру, заставив его показать окошко для ввода логина и пароля.
Как только пользователь заполнит логин и пароль, ссылка, содержащая
PHP-скрипт будет вызвана ещё раз с
<link linkend="reserved.variables">предопределёнными переменными</link>
<varname>PHP_AUTH_USER</varname>, <varname>PHP_AUTH_PW</varname>
и <varname>AUTH_TYPE</varname>, установленными в логин, пароль
и тип аутентификации соответственно. Эти предопределённые
переменные хранятся в массиве <varname>$_SERVER</varname>.
Поддерживаются <emphasis>только</emphasis>: "Basic" и "Digest". Подробнее
смотрите функцию <function>header</function>.
</simpara>
<para>
Пример фрагмента скрипта, который вынуждает клиента авторизоваться для
просмотра страницы:
</para>
<para>
<example>
<title>Пример Basic HTTP-аутентификации</title>
<programlisting role="php">
<![CDATA[
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Текст, отправляемый в том случае,
если пользователь нажал кнопку Cancel';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>Вы ввели пароль {$_SERVER['PHP_AUTH_PW']}.</p>";
}
?>
]]>
</programlisting>
</example>
</para>
<para>
<example>
<title>Пример Digest HTTP-аутентификации</title>
<para>
Это пример реализации простого скрипта Digest HTTP-аутентификации.
За подробностями обращайтесь к <link
xlink:href="&url.rfc;2617">RFC 2617</link>.
</para>
<programlisting role="php">
<![CDATA[
<?php
$realm = 'Запретная зона';
//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');
if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Digest realm="'.$realm.
'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
die('Текст, отправляемый в том случае, если пользователь нажал кнопку Cancel');
}
// анализируем переменную PHP_AUTH_DIGEST
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
!isset($users[$data['username']]))
die('Неправильные данные!');
// генерируем корректный ответ
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
if ($data['response'] != $valid_response)
die('Неправильные данные!');
// все хорошо, логин и пароль верны
echo 'Вы вошли как: ' . $data['username'];
// функция разбора заголовка http auth
function http_digest_parse($txt)
{
// защита от отсутствующих данных
$needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($needed_parts));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$data[$m[1]] = $m[3] ? $m[3] : $m[4];
unset($needed_parts[$m[1]]);
}
return $needed_parts ? false : $data;
}
?>
]]>
</programlisting>
</example>
</para>
<note>
<title>Замечание касательно совместимости</title>
<para>
Будьте особенно внимательны при указании HTTP-заголовков. Для того, чтобы
гарантировать максимальную совместимость с наибольшим количеством
различных клиентов, слово "Basic" должно быть написано с большой буквы "B",
регион (realm) должен быть взят в двойные (не одинарные!) кавычки,
и ровно один пробел должен предшествовать коду <emphasis>401</emphasis> в заголовке
<emphasis>HTTP/1.0 401</emphasis>. Параметры аутентификации должны
разделяться запятыми, как это было показано в примере Digest
аутентификации выше.
</para>
</note>
<para>
Вместо простого отображения на экране переменных <varname>PHP_AUTH_USER</varname>
и <varname>PHP_AUTH_PW</varname>, вам, возможно, понадобится
проверить их корректность. Используйте для этого запрос к базе
данных или поиск пользователя в dbm-файле.
</para>
<para>
Вы можете пронаблюдать особенности работы браузера Internet Explorer.
Он очень требователен к параметру передаваемых заголовков. Трюк с указанием
заголовка <emphasis>WWW-Authenticate</emphasis> перед отправкой статуса
<literal>HTTP/1.0 401</literal> пока что работает для него.
</para>
<note>
<title>Замечание касательно конфигурации</title>
<para>
PHP использует указание директивы <literal>AuthType</literal> для
указания того, используется внешняя аутентификация или нет.
</para>
</note>
<simpara>
Следует заметить, что все вышесказанное не предотвращает похищения паролей к
страницам, требующим авторизацию, кем-либо, кто контролирует страницы без
авторизации, расположенные на том же сервере.
</simpara>
<simpara>
И Netscape Navigator и Internet Explorer очищают кеш аутентификации
текущего окна для заданного региона (realm) при получении от сервера статуса 401.
Это может использоваться для реализации принудительного выхода пользователя
и повторного отображения диалогового окна для ввода имени пользователя и
пароля. Некоторые разработчики используют это для ограничения авторизации по
времени или для предоставления кнопки "Выход".
</simpara>
<para>
<example>
<title>Пример HTTP-аутентификации с принудительным вводом новой пары логин/пароль</title>
<programlisting role="php">
<![CDATA[
<?php
function authenticate() {
header('WWW-Authenticate: Basic realm="Test Authentication System"');
header('HTTP/1.0 401 Unauthorized');
echo "Вы должны ввести корректный логин и пароль для получения доступа к ресурсу \n";
exit;
}
if (!isset($_SERVER['PHP_AUTH_USER']) ||
($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
authenticate();
} else {
echo "<p>Добро пожаловать: " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
echo "Предыдущий логин: " . htmlspecialchars($_REQUEST['OldAuth']);
echo "<form action='' method='post'>\n";
echo "<input type='hidden' name='SeenBefore' value='1' />\n";
echo "<input type='hidden' name='OldAuth' value=\"" . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "\" />\n";
echo "<input type='submit' value='Авторизоваться повторно' />\n";
echo "</form></p>\n";
}
?>
]]>
</programlisting>
</example>
</para>
<simpara>
Это поведение не регламентируется стандартами <literal>HTTP Basic</literal>-аутентификации,
следовательно, вы не должны зависеть от этого. Тестирование браузера <literal>Lynx</literal>
показало, что <literal>Lynx</literal> не очищает кеш авторизации при получении от сервера
статуса 401, и, нажав последовательно "Back", а затем "Forward" возможно
открыть такую страницу, при условии, что требуемые атрибуты авторизации не изменились.
Однако, пользователь может нажать клавишу <literal>'_'</literal> для очистки кеша аутентификации.
</simpara>
<simpara>
Для того, чтобы добиться корректной работы HTTP-аутентификации в IIS сервере с
CGI версией PHP, вы должны отредактировать
конфигурационную настройку IIS под названием "<literal>Directory Security</literal>".
Щёлкните на надписи "<literal>Edit</literal>" и установите опцию
"<literal>Anonymous Access</literal>",
все остальные поля должны остаться неотмеченными.
</simpara>
<note>
<title>Замечание касательно IIS:</title>
<simpara>
Для того, чтобы HTTP-аутентификация корректно работала в IIS, в конфигурации
PHP-опция <link linkend="ini.cgi.rfc2616-headers">cgi.rfc2616_headers</link> должна
быть установлена значением <literal>0</literal> (значение по умолчанию).
</simpara>
</note>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->