Решение проблемы Авторизации и Завершения сеанса с HTTP Authentication: Basic, PHP, Joomla, Apache

от автора

Приветствую

Буквально вчера я решил приступить к разработке личного кабинете одного безымянного сайта. Передо мной встал вопрос по поводу внешнего вида формы авторизации, мне, откровенно, не хотелось заниматься дизайном формы, делать всплывающие подсказки, да и в целом уделять огромное внимание форме. Я сдуру ринулся искать готовые решения, увидел достаточно безвкусных форм. Думал подыскать какой-нибудь готовый компонент, готовое расширение, но в большинстве своём они разочаровали меня. Блуждая по форумам, мне показалось интересным разыграть карту с HTTP Authentication: Basic. Я отправился читать мануал, прежде был недостаточно осведомлён об данном способе. Далее и начались проблемы.

Деваться было некуда, пошастал по сети в поисках сайтов, что возьмутся генерировать формы, код, стили. Тщетны оказались мои попытки облегчить себе задачу. Выход невелик, я приступил к разрешению проблемы. Одно время я старался сварганить решение с помощью .htaccess, нашел такое.

RewriteCond %{HTTP:Authorization} ^Basic.* RewriteRule (.*) index.php?authorization=%{HTTP:Authorization} [QSA,L] 

Увы, у меня возникли проблемы с Joomla, у неё и так всё неплохо в .htaccess, а тут я еще со своим кодом. Уделив время на перебор различных комбинаций, я согласился с тем, что переписывать .htaccess я не буду. С начала код был очень сырым, настолько сырым, что я только-только его скопипастил.

<?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>"; 	} ?> 

Замечательно работает, а передо мной стояла цель реализовать авторизацию с помощью использования уже существующих кодовых слов, что расположены в таблице.

<?php $session = JFactory::getSession(); 	if(!isset($_SERVER['PHP_AUTH_PW'])) { 		header('WWW-Authenticate: Basic realm="My Realm"'); 		header('HTTP/1.0 401 Unauthorized'); 	} else { 		//В случае с обнаружением подходящего codeword - создаём сессию 		if($session->get('user') === null) { 			$db = JFactory::getDbo(); 			$query = $db->getQuery(true); 			$query->select('*'); 			$query->from('#__beda_users'); 			$query->where('codeword = '.$query->quote($_SERVER['PHP_AUTH_PW'])); 			if($res = $db->setQuery($query)->loadAssoc()) { 				$session->set('user', $res); 			} else { 				header('WWW-Authenticate: Basic realm="My Realm"'); 				header('HTTP/1.0 401 Unauthorized'); 			} 		} else { 			//Нам бы сюда 		} 	} ?> 

Работает, значения меняются, сессия создаётся. Замечательно, но в случае с кликом на отмену, значения $_SERVER[‘PHP_AUTH_USER’], $_SERVER[‘PHP_AUTH_PW’] плевать хотели, что ты отменил, после обновления страницы, возвращаются на место. Я решил, что бороться следует с этим через unset. Я добавил строчку.

if($res = $db->setQuery($query)->loadAssoc()) { 	$session->set('user', $res); } else { 	unset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); 	header('WWW-Authenticate: Basic realm="My Realm"'); 	header('HTTP/1.0 401 Unauthorized'); } 

Я старался совладать с этими переменными, но всё глубже уходил в никуда. Устраивал и проверку существования сессии, но тщетно. К тому же мне требовалось сделать завершение сессии, что с слов форумчан мало представляется возможным. Докопался до истины использования адреса вида login:pass@locahost/. Замечательно, переменные изменились $_SERVER[‘PHP_AUTH_USER’], $_SERVER[‘PHP_AUTH_PW’]. Увы, но это не стало моим окончательным решением, поскольку после окончания времени сессии $_SERVER[‘PHP_AUTH_USER’], $_SERVER[‘PHP_AUTH_PW’] продолжали исполнять. Как и после принудительно присваивания $session->set(‘user’, null). Я вне себя от гнева, но знал, что не прощу себе, если позволю отступиться. Я написал отдельное условие для проверки на логаут.

if($_SERVER['PHP_AUTH_USER']=='logout'){ 	$session->set('user', null); 	header('Refresh: 0;URL='); } if(!isset($_SERVER['PHP_AUTH_PW'])) { 	header('WWW-Authenticate: Basic realm="My Realm"'); 	header('HTTP/1.0 401 Unauthorized'); } else { 	//В случае с обнаружением подходящего codeword - создаём сессию 	if($session->get('user') === null) { 		$db = JFactory::getDbo(); 		$query = $db->getQuery(true); 		$query->select('*'); 		$query->from('#__beda_users'); 		$query->where('codeword = '.$query->quote($_SERVER['PHP_AUTH_PW'])); 		if($res = $db->setQuery($query)->loadAssoc()) { 			$session->set('user', $res); 		} else { 			unset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']); 			header('WWW-Authenticate: Basic realm="My Realm"'); 			header('HTTP/1.0 401 Unauthorized'); 		} 	} else { 		//Нам бы сюда 	} } 

Условие сработало, однако после перезагрузки страницы, когда появляется окно с требованием ввести имя пользователя и пароль, оно их приняло, да после обновление страницы, он предложил мне еще раз ввести пароль, нажму «Отмена», $_SERVER[‘PHP_AUTH_USER’] будет logout. Обновлю значения, он присвоит их. А нажму на отмену от вернёт прежние значения. Беда.

В конце концов окончательное решение выглядит так.

$session = JFactory::getSession(); function http_auth($session){ 	$session->set('user', null); 	unset($_SERVER['PHP_AUTH_PW'],  $_SERVER['PHP_AUTH_USER']); 	header('WWW-Authenticate: Basic realm="Auth"'); 	header('HTTP/1.0 401 Unauthorized'); } if($_SERVER['PHP_AUTH_USER']=='logout'){ 	$session->set('user', null); 	header('Refresh: 0;URL='); } if($session->get('user') === null){ 	if(!isset($_SERVER['PHP_AUTH_PW'])){ 		http_auth($session); 	} else { 		$pw = $_SERVER['PHP_AUTH_PW']; 		$db = JFactory::getDbo(); 		$query = $db->getQuery(true); 		$query->select('*'); 		$query->from('#__beda_users'); 		$query->where('codeword = '.$query->quote($pw)); 		if($res = $db->setQuery($query)->loadAssoc()){ 			$session->set('user', $res); 		} else { 			http_auth($session); 		} 	} } else { 	if(!isset($_SERVER['PHP_AUTH_PW'])){ 		http_auth($session); 	} } 
На звание правильного, красивого, читабельного кода не претендую, это работает, а после можно уже и почистить.

Первые пример.
http://www.php.net/manual/ru/features.http-auth.php

ссылка на оригинал статьи http://habrahabr.ru/post/209840/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *