Аутентификация в ODataDB
Содержание
- Введение
- Схемы аутентификации
- HTTP и HTTPS
- Аутентификация пользователей
- Пример аутентификации хранимыми процедурами
Введение
ODataDB создает конечные точки для каждого подключения, определенного в файле appsettings.
Если строки подключения содержат шаблоны user
и pass
, ODataDB требует имя пользователя и пароль.
Для аутентификации ODataDB заменяет шаблоны на полученные значения и пытается подключиться к базе данных.
Например, файл appsettings.json
может содержать следующее:
{ "ConnectionStrings": { "mssql": { "ProviderName": "System.Data.SqlClient", "ConnectionString": "Data Source=.\\SQLEXPRESS;Initial Catalog=master;User ID=user;Pwd=pass" }, "mssql-023": { "ProviderName": "System.Data.SqlClient", "ConnectionString": "Data Source=mssql.savetodb.com;Initial Catalog=AzureDemo100;User ID=sample02_user3;Pwd=Usr_2011#_Xls4168" } } }
В этом примере конечные точки mssql
требуют аутентификации, в то время как mssql-023
— нет.
Схемы аутентификации
ODataDB поддерживает:
- Аутентификацию Basic, как определено в стандарте RFC2617.
- Аутентификацию JWT.
Выбор схемы аутентификации осуществляется через свойство Auth
в файле appsettings.
При использовании JWT также доступна аутентификация Basic.
Обе схемы безопасны при использовании HTTPS.
Для аутентификации Basic ODataDB возвращает ошибку 401 "Unauthorized" при неавторизованных запросах к любым ресурсам.
Для аутентификации JWT ODataDB возвращает ошибку 403 "Forbidden" при неавторизованных запросах только к защищенным ресурсам.
HTTP и HTTPS
Не используйте ODataDB по протоколу HTTP, кроме localhost, так как имена и пароли передаются в открытом виде.
Всегда используйте HTTPS и настраивайте перенаправление HTTP-запросов на HTTPS.
Аутентификация пользователей
ODataDB поддерживает два способа проверки логина и пароля пользователя:
- Использование логина и пароля пользователя в базе данных.
- Использование хранимых процедур.
Первый способ используется по умолчанию. ODataDB заменяет шаблоны user
и pass
в строке подключения и пытается подключиться к базе данных.
Если подключение успешно, ODataDB загружает модель и обрабатывает запросы пользователя. В противном случае возвращается ошибка подключения.
Во втором способе ODataDB вызывает хранимую процедуру, передавая имя пользователя и пароль.
Процедура проверяет данные пользователя и возвращает пустое сообщение об ошибке при успехе или сообщение об ошибке при неудаче.
Это традиционный подход для веб-приложений, который позволяет управлять пользователями без создания логинов в базе данных.
Пример аутентификации хранимыми процедурами
Предположим, у нас есть база данных marketplace
для обслуживания покупателей и продавцов.
В ней есть таблица user
с необходимыми полями: id
, uid
, username
, email
, password_hash
, role
, seller_id
.
Необходимо проверять данные пользователя с помощью процедуры usp_sign_in
и выполнять последующие запросы от имени пользователей с ролями buyer
или seller
, передавая в процедуры полученные идентификаторы пользователя и продавца.
Использование разных логинов для разных ролей позволяет настраивать разрешения и получать различные модели. Таким образом, покупатели будут видеть только объекты для покупателей, а продавцы — объекты для продавцов.
Вот пример конфигурации:
"marketplace": { "ProviderName": "MySqlConnector", "ConnectionString": "Server=localhost;Password=pass;User ID=user;Database=marketplace", "SignIn": "marketplace.usp_sign_in", "AuthContextParams": "auth_user_id auth_seller_id", "RoleUsers": { "auth": { "Username": "marketplace_auth", "Password": "Usr_2011#_Xls4168" }, "default": { "Username": "marketplace_buyer", "Password": "Usr_2011#_Xls4168" }, "buyer": { "Username": "marketplace_buyer", "Password": "Usr_2011#_Xls4168" }, "seller": { "Username": "marketplace_seller", "Password": "Usr_2011#_Xls4168" } } },
См. полное описание полей в файле appsettings.
Вот важные замечания:
SignIn
содержит имя процедуры для проверки пользователей.RoleUsers
включает обязательную секциюauth
с данными подключения для выполнения процедуры проверки пользователей.RoleUsers
включает обязательную секциюdefault
с данными подключения, когда роль пользователя не определена.RoleUsers
содержит секцииbuyer
иseller
с данными пользователей для соответствующих ролей.AuthContextParams
содержит имена полей, которые возвращаются процедурой проверки и должны передаваться как параметры в процедуры последующих запросов пользователя.
Пример хранимой процедуры на диалекте MySQL:
DROP PROCEDURE IF EXISTS usp_sign_in; DELIMITER // CREATE DEFINER=marketplace_dev
@localhost
PROCEDURE usp_sign_in(email varchar(50),password
varchar(50)) BEGIN DECLARE user_id int; DECLARE uid varchar(50); DECLARE role varchar(50); DECLARE seller_id int; DECLARE matched tinyint; SELECT u.id, u.uid, u.role, u.seller_id, CASE WHEN get_password_hashed(password
, u.password_hash) = u.password_hash THEN 1 ELSE 0 END AS matched INTO user_id, uid, role, seller_id, matched FROM user u WHERE u.email = LOWER(email) OR u.username = LOWER(email) LIMIT 1; SELECT CASE WHEN matched = 1 THEN user_id ELSE NULL END AS auth_user_id, CASE WHEN matched = 1 THEN uid ELSE NULL END AS uid, CASE WHEN matched = 1 THEN role ELSE NULL END AS role, CASE WHEN matched = 1 THEN seller_id ELSE NULL END AS auth_seller_id, CASE WHEN matched = 1 THEN NULL WHEN user_id IS NOT NULL THEN 'Password not matched' ELSE 'User not found' END AS message; END // DELIMITER ; GRANT EXECUTE ON PROCEDURE usp_sign_in TO 'marketplace_auth'@'localhost';
Обратите внимание на важные моменты:
- Процедура должна принимать два параметра: имя пользователя и пароль. Порядок важен, имена — нет.
- Для имени пользователя должен использоваться один параметр, даже если пользователь может использовать имя или почту. Просто проверяйте оба варианта.
- В поле
message
следует вернуть пустое сообщение для успеха или сообщение об ошибке. - Установите разрешение
EXECUTE
на процедуру проверки пользователей для пользователя, указанного в секцииRoleUsers
:auth
.