Аутентификация в ODataDB
Содержание
- Введение
- Схемы аутентификации
- HTTP и HTTPS
- Аутентификация пользователей
- Пример аутентификации хранимыми процедурами
Введение
ODataDB создает конечные точки для каждого подключения, определенного в файле appsettings.
ODataDB требует имя пользователя и пароль, если строки подключения содержат шаблоны user
и pass
.
Для аутентификации, 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
с данными пользователей для ролей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
.