Настройка авторизации через OAUTH2 сервера https://oauth2.volmed.org.ru: различия между версиями
Перейти к навигации
Перейти к поиску
Misha (обсуждение | вклад) |
Misha (обсуждение | вклад) |
||
(не показано 6 промежуточных версий этого же участника) | |||
Строка 9: | Строка 9: | ||
$GLOBALS['jwt_key'] = 'sdklfwiomwefwepiojwepjowfmwfmwef'; // Строка с набором символов для шифрования JWT токена | $GLOBALS['jwt_key'] = 'sdklfwiomwefwepiojwepjowfmwfmwef'; // Строка с набором символов для шифрования JWT токена | ||
$GLOBALS['max_time'] = 3600 * 24 * 7; // Время жизни COOKIES, например, 7 суток | $GLOBALS['max_time'] = 3600 * 24 * 7; // Время жизни COOKIES, например, 7 суток | ||
$oauth2_url = 'https://oauth2.volmed.org.ru'; // URL сервиса авторизации | |||
$GLOBALS['oauth2_url'] = $oauth2_url; | |||
$redirect_uri = $http."://$_SERVER[HTTP_HOST]"; | |||
$GLOBALS['redirect_uri'] = $redirect_uri; | |||
</pre> | </pre> | ||
#Для работы с JWT токеном используем библиотеку https://github.com/firebase/php-jwt. Ее нужно установить в каталог class/jwt | #Для работы с JWT токеном используем библиотеку https://github.com/firebase/php-jwt. Ее нужно установить в каталог class/jwt | ||
==Хранение пользовательских данных в COOKIES== | |||
Самое простое для моего случая - хранить в куках id пользователя и время создания куков. Тк все данные пользователя, я могу вытащить из БД по его id.<br> | |||
Их нужно зашифровать с помощью JWT и хранить полученное значение в куках. | |||
<pre> | |||
protected function set_cookie() | |||
{ | |||
/* | |||
* Устанавливаем COOKIE | |||
*/ | |||
if (empty($this->login_expires_set)) { | |||
$this->login_expires_set = 0; | |||
} | |||
if (empty($_COOKIE['jwt']) && !empty($this->auth['id'])) { | |||
$payload = [ | |||
'id_user' => !empty($this->auth['id_real']) ? $this->auth['id_real'] : $this->auth['id'], | |||
'time_beg' => time(), | |||
]; | |||
setcookie('jwt', JWT::encode($payload, $GLOBALS['jwt_key'], 'HS256'), [ | |||
"expires" => strtotime($this->login_expires_set), | |||
"path" => "/", | |||
"httponly" => true, | |||
]); | |||
} | |||
} | |||
<pre> | |||
И проверка кукис | |||
<pre> | |||
protected function load_cookie() | |||
{ | |||
/* | |||
* Метод по проверке COOKIE и загрузки их в переменные для проверки авторизации | |||
*/ | |||
if (!empty($_COOKIE['jwt'])) { | |||
$decoded_obj = JWT::decode($_COOKIE['jwt'], new Key($GLOBALS['jwt_key'], 'HS256')); | |||
$decoded = get_object_vars($decoded_obj); | |||
$this->id_user = $decoded['id_user']; | |||
$this->time_beg = $decoded['time_beg']; | |||
} | |||
} | |||
<pre> | |||
==Формирование строки авторизации== | |||
Для перехода на страницу сервера авторизации, генерим следующий код | |||
<pre> | |||
if (!empty($_GET['code'])) { // Если это уже ответ oauth2 сервера (Есть параметр state) | |||
if ($_GET['state'] == $_SESSION['state']) { // Если state совпадает с сохраненным в Сессии | |||
$oauth2_access = $this->oauth2_post(); // Посылаем уже с помощью POST запрос | |||
$this->auth = $this->auth($oauth2_access); // И после возврата id пользователя, обрабатываем его вход | |||
} else die('Ошибка авторизации (Invalid state), обратитесь к администраотру сайта'); // если state не совпал, то ошибка | |||
} else { // Ето первый цикл обращения к oauth2 серверу | |||
$permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; // список символов, из которых будем генерить state | |||
$state = generate_string($permitted_chars, 20); // Генерим код state - 20 символов случайного кода | |||
$_SESSION['state'] = $state; // Сохраняем в сессии | |||
$url_data = [ | |||
'response_type' => 'code', | |||
'client_id' => $GLOBALS['id_resource'], // ID сервиса в МИАЦ | |||
'state' => $state, // Случайный код, который сервис должен вернуть | |||
'redirect_uri' => $GLOBALS['redirect_uri'] // Адрес возврата дб вв виде https://sait.volmed.org.ru | |||
]; | |||
$url = $GLOBALS['oauth2_url'] . '?' . http_build_query($url_data); // URL для отправки на сервер авторизации | |||
header('Location:' . $url); // | |||
exit; | |||
} | |||
</pre> | |||
После перехода на сервер авторизации, вводим Логин и Пароль. И если он правильный, то сервер возвращает на страницу редиректа | |||
==Формирование POST запроса авторизации== | |||
<pre> | |||
private function oauth2_post() | |||
{ | |||
$post_data = [ | |||
"user_id" => $_GET['user_id'], // ID пользователя, возвращенного oauth2 серверром | |||
"code" => $_GET['code'], | |||
'grant_type' => 'authorization_code', // Тип гранта | |||
'client_id' => $GLOBALS['id_resource'], // ID сервиса | |||
'client_secret' => 'wetreyrtbv:KJLKO', // это код из БД OUTH2 сервера таблица oauth_clients.client_secret для $GLOBALS['id_resource'] | |||
'redirect_uri' => $GLOBALS['redirect_uri'], | |||
// 'scope' => 'read write', | |||
]; | |||
$data_string = json_encode($post_data); | |||
$ch = curl_init(); | |||
curl_setopt($ch, CURLOPT_URL, $GLOBALS['oauth2_url'] . '/token'); | |||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); | |||
curl_setopt($ch, CURLOPT_POST, true); | |||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); | |||
curl_setopt($ch, CURLOPT_HTTPHEADER, array( | |||
'Content-Type: application/json', | |||
'Content-Length: ' . strlen($data_string), | |||
)); | |||
$oauth2_access = []; | |||
$output = curl_exec($ch); | |||
// execute the request | |||
if ($output === false) echo 'Ошибка curl: ' . curl_error($ch); | |||
else { | |||
$oauth2_access = json_decode($output, true); | |||
if (!empty($oauth2_access['error'])) { | |||
printr($oauth2_access); | |||
exit(); | |||
} | |||
$oauth2_access['id_user'] = $_GET['user_id']; | |||
} | |||
curl_close($ch); | |||
return $oauth2_access; | |||
} | |||
</pre> | |||
==Запрос пользовательских данных== | |||
<pre> | |||
public function take_userinfo() | |||
{ | |||
$accessToken = $this->access_token; // <-- access token | |||
$userInfoUrl = $GLOBALS['oauth2_url'] . '/userinfo'; // <-- endpoint | |||
$ch = curl_init(); | |||
curl_setopt($ch, CURLOPT_URL, $userInfoUrl); | |||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |||
curl_setopt($ch, CURLOPT_HTTPHEADER, [ | |||
'Authorization: Bearer ' . $accessToken, | |||
'Accept: application/json' | |||
]); | |||
$response = curl_exec($ch); | |||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |||
if (curl_errno($ch)) { | |||
echo 'Ошибка cURL: ' . curl_error($ch); | |||
} elseif ($httpCode !== 200) { | |||
echo "Ошибка HTTP $httpCode: $response"; | |||
} else { | |||
$userData = json_decode($response, true); | |||
//printr($userData); | |||
} | |||
curl_close($ch); | |||
return $userData; | |||
} | |||
</pre> |
Текущая версия от 10:55, 7 мая 2025
Подготовительные операции
- Идем в БД oauth_db на сервере 172.16.130.31 и добавляем в таблицу oauth_clients
- client_id - Номер WEB интерфейса, который вы собираетесь подключить
- client_secret - Набор любых символов для шифрования
- Добавляем в настроечный файл сервиса следующие строки
$GLOBALS['id_resource'] = 7; // Номер WEB интерфейса $PassLength=5; //длина пароля $GLOBALS['jwt_key'] = 'sdklfwiomwefwepiojwepjowfmwfmwef'; // Строка с набором символов для шифрования JWT токена $GLOBALS['max_time'] = 3600 * 24 * 7; // Время жизни COOKIES, например, 7 суток $oauth2_url = 'https://oauth2.volmed.org.ru'; // URL сервиса авторизации $GLOBALS['oauth2_url'] = $oauth2_url; $redirect_uri = $http."://$_SERVER[HTTP_HOST]"; $GLOBALS['redirect_uri'] = $redirect_uri;
- Для работы с JWT токеном используем библиотеку https://github.com/firebase/php-jwt. Ее нужно установить в каталог class/jwt
Хранение пользовательских данных в COOKIES
Самое простое для моего случая - хранить в куках id пользователя и время создания куков. Тк все данные пользователя, я могу вытащить из БД по его id.
Их нужно зашифровать с помощью JWT и хранить полученное значение в куках.
protected function set_cookie() { /* * Устанавливаем COOKIE */ if (empty($this->login_expires_set)) { $this->login_expires_set = 0; } if (empty($_COOKIE['jwt']) && !empty($this->auth['id'])) { $payload = [ 'id_user' => !empty($this->auth['id_real']) ? $this->auth['id_real'] : $this->auth['id'], 'time_beg' => time(), ]; setcookie('jwt', JWT::encode($payload, $GLOBALS['jwt_key'], 'HS256'), [ "expires" => strtotime($this->login_expires_set), "path" => "/", "httponly" => true, ]); } } <pre> И проверка кукис <pre> protected function load_cookie() { /* * Метод по проверке COOKIE и загрузки их в переменные для проверки авторизации */ if (!empty($_COOKIE['jwt'])) { $decoded_obj = JWT::decode($_COOKIE['jwt'], new Key($GLOBALS['jwt_key'], 'HS256')); $decoded = get_object_vars($decoded_obj); $this->id_user = $decoded['id_user']; $this->time_beg = $decoded['time_beg']; } } <pre> ==Формирование строки авторизации== Для перехода на страницу сервера авторизации, генерим следующий код <pre> if (!empty($_GET['code'])) { // Если это уже ответ oauth2 сервера (Есть параметр state) if ($_GET['state'] == $_SESSION['state']) { // Если state совпадает с сохраненным в Сессии $oauth2_access = $this->oauth2_post(); // Посылаем уже с помощью POST запрос $this->auth = $this->auth($oauth2_access); // И после возврата id пользователя, обрабатываем его вход } else die('Ошибка авторизации (Invalid state), обратитесь к администраотру сайта'); // если state не совпал, то ошибка } else { // Ето первый цикл обращения к oauth2 серверу $permitted_chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; // список символов, из которых будем генерить state $state = generate_string($permitted_chars, 20); // Генерим код state - 20 символов случайного кода $_SESSION['state'] = $state; // Сохраняем в сессии $url_data = [ 'response_type' => 'code', 'client_id' => $GLOBALS['id_resource'], // ID сервиса в МИАЦ 'state' => $state, // Случайный код, который сервис должен вернуть 'redirect_uri' => $GLOBALS['redirect_uri'] // Адрес возврата дб вв виде https://sait.volmed.org.ru ]; $url = $GLOBALS['oauth2_url'] . '?' . http_build_query($url_data); // URL для отправки на сервер авторизации header('Location:' . $url); // exit; }
После перехода на сервер авторизации, вводим Логин и Пароль. И если он правильный, то сервер возвращает на страницу редиректа
Формирование POST запроса авторизации
private function oauth2_post() { $post_data = [ "user_id" => $_GET['user_id'], // ID пользователя, возвращенного oauth2 серверром "code" => $_GET['code'], 'grant_type' => 'authorization_code', // Тип гранта 'client_id' => $GLOBALS['id_resource'], // ID сервиса 'client_secret' => 'wetreyrtbv:KJLKO', // это код из БД OUTH2 сервера таблица oauth_clients.client_secret для $GLOBALS['id_resource'] 'redirect_uri' => $GLOBALS['redirect_uri'], // 'scope' => 'read write', ]; $data_string = json_encode($post_data); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $GLOBALS['oauth2_url'] . '/token'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($data_string), )); $oauth2_access = []; $output = curl_exec($ch); // execute the request if ($output === false) echo 'Ошибка curl: ' . curl_error($ch); else { $oauth2_access = json_decode($output, true); if (!empty($oauth2_access['error'])) { printr($oauth2_access); exit(); } $oauth2_access['id_user'] = $_GET['user_id']; } curl_close($ch); return $oauth2_access; }
Запрос пользовательских данных
public function take_userinfo() { $accessToken = $this->access_token; // <-- access token $userInfoUrl = $GLOBALS['oauth2_url'] . '/userinfo'; // <-- endpoint $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $userInfoUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $accessToken, 'Accept: application/json' ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if (curl_errno($ch)) { echo 'Ошибка cURL: ' . curl_error($ch); } elseif ($httpCode !== 200) { echo "Ошибка HTTP $httpCode: $response"; } else { $userData = json_decode($response, true); //printr($userData); } curl_close($ch); return $userData; }