Аутентификация в ODataDB

Аутентификация в ODataDB

Содержание

Введение

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 поддерживает два способа проверки логина и пароля пользователя:

  1. Использование логина и пароля пользователя в базе данных.
  2. Использование хранимых процедур.

Первый способ используется по умолчанию. 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.

Вот важные замечания:

  1. SignIn содержит имя процедуры для проверки пользователей.
  2. RoleUsers включает обязательную секцию auth с данными подключения для выполнения процедуры проверки пользователей.
  3. RoleUsers включает обязательную секцию default с данными подключения, когда роль пользователя не определена.
  4. RoleUsers содержит секции buyer и seller с данными пользователей для соответствующих ролей.
  5. 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';

Обратите внимание на важные моменты:

  1. Процедура должна принимать два параметра: имя пользователя и пароль. Порядок важен, имена — нет.
  2. Для имени пользователя должен использоваться один параметр, даже если пользователь может использовать имя или почту. Просто проверяйте оба варианта.
  3. В поле message следует вернуть пустое сообщение для успеха или сообщение об ошибке.
  4. Установите разрешение EXECUTE на процедуру проверки пользователей для пользователя, указанного в секции RoleUsers: auth.

Этот веб-сайт использует куки. Продолжая использовать веб-сайт, Вы принимаете условия Политики защиты персональных данных.

fixed-footer