Аутентификация в 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@localhostPROCEDURE usp_sign_in(email varchar(50),passwordvarchar(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.