В этой статье мы прикрутим авторизацию через Active Directory к Asterisk CDR Viewer используя PHP скрипт. Это решение актуально для авторизации корпоративных пользователей, которым нужно предоставить доступ к какому-то web ресурсу внутри сети на основе присутствия пользователя в группе в домене AD. Вы можете легко переделать скрипт под свои нужны и использовать для доступа к подобным сервисам или страничкам.
Для использования нужных функций нам понадобится установить модуль php-ldap.
Далее мы создадим группу в AD с именем Статистика Asterisk и включим в неё всех пользователей, которым необходим доступ.
Итак, сначала создадим файл ldap.php в папке Asterisk CDR Viewer. В нем опишем настройки доступа к AD серверу:
Для проверки авторизации используется функция login(), которая получает логин и пароль при заполнении формы. В случае ввода правильных данных происходит переадресация на основой файл index.php. За авторизацию у нас будет отвечать файл auth.php в той же папке:
./img/auth.css
В идеале пустить трафик от сервера со статистикой до AD сервера через отдельную недоступную подсеть (или vpn) для того, чтобы имена и пароли для авторизации не смогли перехватить.
Для использования нужных функций нам понадобится установить модуль php-ldap.
Далее мы создадим группу в AD с именем Статистика Asterisk и включим в неё всех пользователей, которым необходим доступ.
Итак, сначала создадим файл ldap.php в папке Asterisk CDR Viewer. В нем опишем настройки доступа к AD серверу:
<?php
//IP адрес сервера AD
$ldaphost = "192.168.0.100";
//Порт
$ldapport = "389";
//Путь к группе в которой должна быть учетка сотрудника,
//что бы пройти аутентификацию.
$memberof = "cn=Статистика Asterisk,ou=CompanyName,dc=domain,dc=local";
//Откуда начинаем искать
$base = "dc=domain,dc=local";
//Фильтр по которому будем аутентифицировать пользователя
$filter = "sAMAccountName=";
//Ваш домен, обязательно с собакой впереди.
$domain = "@domain.local";
?>
Чтобы при обновлении страницы не приходилось проходить авторизацию повторно мы сохраним данные в сессии пользователя. Для этого я использовал класс AuthClass который взял отсюда и внес свои изменения. Для проверки авторизации используется функция login(), которая получает логин и пароль при заполнении формы. В случае ввода правильных данных происходит переадресация на основой файл index.php. За авторизацию у нас будет отвечать файл auth.php в той же папке:
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Статистика звонков IP телефонии</title>
<link rel="stylesheet" href="img/auth.css">
</head>
<body>
<?php
session_start(); //Запускаем сессии
/**
* Класс для авторизации
* @author дизайн студия ox2.ru
*/
class AuthClass {
/**
* Проверяет, авторизован пользователь или нет
* Возвращает true если авторизован, иначе false
* @return boolean
*/
public function isAuth() {
if (isset($_SESSION["is_auth"])) { //Если сессия существует
return $_SESSION["is_auth"]; //Возвращаем значение переменной сессии is_auth (хранит true если авторизован, false если не авторизован)
}
else return false; //Пользователь не авторизован, т.к. переменная is_auth не создана
}
/**
* Авторизация пользователя
* @param string $login
* @param string $passwors
*/
public function auth() {
//проверяем авторизацию в функции login()
if (login() != false) {
$_SESSION["is_auth"] = true; //Делаем пользователя авторизованным
return true;
}
else { //Логин и пароль не подошел
return false;
}
}
/**
* Метод возвращает логин авторизованного пользователя
*/
public function getLogin() {
if ($this->isAuth()) { //Если пользователь авторизован
return $_SESSION["fullname"]; //Возвращаем логин, который записан в сессию
}
}
public function out() {
$_SESSION = array(); //Очищаем сессию
session_destroy(); //Уничтожаем
}
} /* class AuthClass ends */
$auth = new AuthClass();
if (!empty($_POST['username']) && !empty($_POST['password'])) //Если логин и пароль были введены
{
$auth->auth(); //проверяем авторизацию
}
if (isset($_GET["is_exit"])) { //Если нажата кнопка выхода
if ($_GET["is_exit"] == 1) {
$auth->out(); //Выходим
header("Location: auth.php?is_exit=0"); //Редирект после выхода
}
}
if ($auth->isAuth()) { // Если пользователь авторизован
/* Здесь выполняется код при успешной авторизации пользователя */
header("Location: /index.php"); //перенаправляем его на главную страницу скрипта Asterisk CDR Viewer
}
else { //Если не авторизован, показываем форму ввода логина и пароля
?>
<div class="login-page">
<div class="form">
<form class="login-form" method="post" action="auth.php" >
Авторизуйтесь<br>для доступа к статистике</p>
<input type="text" placeholder="Имя в домене" id="username" name="username"/>
<input type="password" placeholder="Пароль" type="password" name="password">
<input type="submit" value="Войти" name="log_in" >
<?php if (!empty($login_error)) {echo "<div style="."color:red;".">".$login_error."</div>";} ?>
</form>
</div>
</div>
<?php } ?>
<?php
//Проверяем данные пользователя, используя LDAP
function login () {
require_once "ldap.php"; // Конфиг для подключения к ldap
global $login_error; // Сюда запишем текст ошибки, если авторизация не пройдена
$username = $_POST['username'];
$login = $_POST['username'].$domain;
$password = $_POST['password'];
//подсоединяемся к LDAP серверу
$ldap = ldap_connect($ldaphost,$ldapport) or die('Cannot connect to LDAP Server.');
//Включаем LDAP протокол версии 3
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3) or die('Unable to set LDAP protocol version');
//Отключаем обработку рефералов для ldap v3
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0) or die('Unable to set LDAP OPT REFERRALS');
if ($ldap) /* Получаем данные из AD */
{
// Пытаемся войти в LDAP при помощи введенных логина и пароля
$bind = ldap_bind($ldap,$login,$password);
if ($bind) //Привязка LDAP прошла успешно!
{
// Проверим, является ли пользователь членом указанной группы и не отключен ли он.
$result = ldap_search($ldap,$base,"(&(memberOf=".$memberof.")(".$filter.$username.")(!(userAccountControl:1.2.840.113556.1.4.803:=2)))");
if (!$result) {
$login_error = 'Ошибка обращения к LDAP.';
return false;
}
// Получаем количество результатов предыдущей проверки
$result_ent = ldap_get_entries($ldap,$result);
if (!$result_ent)
{
$login_error = 'Результатов проверки получить не удалось';
return false;
}
}
else
{
$login_error = 'Вы ввели неправильный <br>логин или пароль';
return false;
}
ldap_close($ldap); /* Закрываем соединение */
}
/* Смотрим результаты */
// Если пользователь найден, т.е. результатов больше 0 (1 должен быть)
if ($result_ent['count'] != 0)
{
// тут код в случае если авторизации пройдена
$fullname = $result_ent[0]["displayname"][0]; //полное имя пользователя
$_SESSION["fullname"] = $fullname; //сохраняем в переменной сессии для отображения
return true;
exit;
}
else
{
$login_error = 'К сожалению, вам доступ закрыт.';
return false;
}
}
?>
</body>
</html>
В файл index.php (Asterisk CDR Viewer) вверху нужно добавить код, который будет проверять авторизован ли пользователь (смотреть переменную сессии) и отправлять на форму ввода имени и пароля в случае, если пользователь не авторизован (переменная сессии не установлена).//Проверяем, авторизацию пользователя
session_start();
if(!isset($_SESSION["is_auth"]))
{
//если пользователь не авторизован отправляем его на страницу авторизации
header("Location: auth.php");
exit;
}
Ну и стили для формы авторизации у меня получились такие:./img/auth.css
.login-page {
width: 360px;
padding: 8% 0 0;
margin: auto;
}
.form {
position: relative;
z-index: 1;
background: #FFFFFF;
max-width: 360px;
margin: 0 auto 100px;
padding: 45px;
text-align: center;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
font-family: Helvetica, Arial, sans-serif;
outline: 0;
background: #f2f2f2;
width: 100%;
border: 0;
margin: 0 0 15px;
padding: 15px;
box-sizing: border-box;
font-size: 14px;
}
.form button {
font-family: Helvetica, Arial, sans-serif;
text-transform: uppercase;
outline: 0;
background: #4CAF50;
width: 100%;
border: 0;
padding: 15px;
color: #FFFFFF;
font-size: 14px;
-webkit-transition: all 0.3 ease;
transition: all 0.3 ease;
cursor: pointer;
}
.form button:hover,.form button:active,.form button:focus {
background: #43A047;
}
.form .message {
margin: 15px 0 0;
color: #b3b3b3;
font-size: 12px;
}
.form .message a {
color: #4CAF50;
text-decoration: none;
}
.form .register-form {
display: none;
}
.container {
position: relative;
z-index: 1;
max-width: 300px;
margin: 0 auto;
}
.container:before, .container:after {
content: "";
display: block;
clear: both;
}
.container .info {
margin: 50px auto;
text-align: center;
}
.container .info h1 {
margin: 0 0 15px;
padding: 0;
font-size: 36px;
font-weight: 300;
color: #1a1a1a;
}
.container .info span {
color: #4d4d4d;
font-size: 12px;
}
.container .info span a {
color: #000000;
text-decoration: none;
}
.container .info span .fa {
color: #EF3B3A;
}
body {
background: #B8F0FF;
background: -webkit-linear-gradient(right, #B8F0FF, #187b96);
background: -moz-linear-gradient(right, #B8F0FF, #187b96);
background: -o-linear-gradient(right, #B8F0FF, #187b96);
background: linear-gradient(to left, #B8F0FF, #187b96);
font-family: Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
Осталось добавить ссылку для выхода из статистики вверху страницы. Для этого открываем файл ./templates/header.php и вписываем следующий код внизу перед последним закрывающим тегом </table><?php
//Показываем кнопку выхода
echo "<br/><div style='color: #3c8dbc;text-align: right;font-size: 13px;margin-right:6px;'><a href='auth.php?is_exit=1'>Завершить сеанс? (".$_SESSION["fullname"].")</a></div>";
?>
Следует добавить, что время активности сессии по умолчанию составляет 24 минуты. По прошествии этого времени пользователю нужно будет заново пройти авторизацию. В моём случае этого времени достаточно, но если вы хотите увеличить время, можете изменить настройки php.ini на вашем сервере, либо добавить в код такую функцию: ini_set('session.gc_maxlifetime', 86400); Это увеличит время до 1 суток.Безопасность
Для того, чтобы пароли не передавались в открытом виде, доступ к статистике нужно предоставить по HTTPS протоколу (сгенерировать SSL сертификат) и разрешить только нужную подсеть (или диапазона адресов) средствами web сервера и/или файрвола.В идеале пустить трафик от сервера со статистикой до AD сервера через отдельную недоступную подсеть (или vpn) для того, чтобы имена и пароли для авторизации не смогли перехватить.
Постоянно "К сожалению, вам доступ закрыт." Не понимаю как исправить, логов нет (
ОтветитьУдалитьПроверьте настройки ldap подключения, фильтра ($memberof). Пользователь AD должен быть в группе с именем "Статистика Asterisk".
УдалитьЗдравствуйте, можете подсказать, возвращается ошибка Warning: ldap_search(): Search: Operations error in /var/www/html/auth.php on line 117 в файле эта строчка выглядит как:
ОтветитьУдалить$result = ldap_search($ldap,$base,"(&(memberOf=".$memberof.")(".$filter.$username.")(!(userAccountControl:1.2.840.113556.1.4.803:=2)))");
Так же ранее получил ошибку на работу ф-ии session_start(); в файле auth.php переместил ее в начало файла ошибку ушла
В любом случаи спасибо за Ваш труд в написании данной статьи)
Здравствуйте, можете подсказать, возвращается ошибка Warning: ldap_search(): Search: Operations error in /var/www/html/auth.php on line 117 в файле эта строчка выглядит как:
ОтветитьУдалить$result = ldap_search($ldap,$base,"(&(memberOf=".$memberof.")(".$filter.$username.")(!(userAccountControl:1.2.840.113556.1.4.803:=2)))");
Так же ранее получил ошибку на работу ф-ии session_start(); в файле auth.php переместил ее в начало файла ошибку ушла
В любом случаи спасибо за Ваш труд в написании данной статьи)
Спасибо за отзыв. По поводу вашей ошибки: у вас установлен модуль php-ldap? Какая версия php используется?
Удалить