Как реализовать JWT-аутентификацию с динамической базой данных в Django? (Таблица пользователей находится в каждой базе данных, она не центральная)
Я работаю над Django-приложением, в котором данные пользователей не хранятся в центральной базе данных. Вместо этого у каждого клиента есть своя отдельная база данных, размещенная на собственном сервере.
Вот установка:
- JWT Authentication используется для приложения.
- Центральный Django-сервер обрабатывает запросы на аутентификацию, но должен динамически подключаться к базе данных клиента на основе информации, предоставленной в JWT-токене.
- Токен
employee_id
хранится в базе данных каждого клиента, а не в центральной базе данных Django. - Строка подключения к базе данных клиента включается в полезную нагрузку JWT-токена.
Моя реализация:
Я создал пользовательский класс JWTAuthentication
, в котором:
- Token Validation: JWT-токен проверяется.
- Подключение к базе данных: На основе полезной нагрузки токена я динамически подключаюсь к базе данных клиента, используя строку подключения, указанную в токене.
- Проверка пользователя: Я получаю пользователя из базы данных клиента, используя
employee_id
в токене, и проверяю, активен ли пользователь.
Вот упрощенная версия моего JWTAuthentication
класса:
from rest_framework import authentication
from rest_framework.request import Request
from .models import TokenUser
from .settings import api_settings
from .tokens import Token
from .exceptions import AuthenticationFailed, InvalidToken
import pymssql
class JWTAuthentication(authentication.BaseAuthentication):
def authenticate(self, request: Request):
header = self.get_header(request)
if header is None:
return None
raw_token = self.get_raw_token(header)
if raw_token is None:
return None
validated_token = self.get_validated_token(raw_token)
return self.get_user(validated_token), validated_token
def get_user(self, validated_token: Token):
employee_id = validated_token.get(api_settings.USER_ID_CLAIM)
conn_string = validated_token.get('conn')
role = validated_token.get('role')
if not employee_id:
raise InvalidToken("Token contained no recognizable user identification")
if role == 0:
# Local database user fetching logic
try:
user = self.user_model.objects.get(**{api_settings.USER_ID_FIELD: employee_id})
if not user.is_active:
raise AuthenticationFailed("User is inactive", code="user_inactive")
return user
except self.user_model.DoesNotExist:
raise AuthenticationFailed("User not found", code="user_not_found")
else:
# External database connection logic
if not conn_string:
raise InvalidToken("Token contained no connection string")
def reconnect(conn_string):
conn_details = conn_string.split(':')
server, database, username, password = conn_details[1:5]
return pymssql.connect(server=server, user=username, password=password, database=database)
with reconnect(conn_string) as connection:
cursor = connection.cursor()
cursor.execute("""
SELECT [btEmpIsActive]
FROM [tblMstEmployee]
WHERE [inEmpId] = %s
""", [employee_id])
row = cursor.fetchone()
if not row:
raise AuthenticationFailed("User not found in the external database", code="user_not_found")
is_active = row[0]
if not is_active:
raise AuthenticationFailed("User is inactive in the external database", code="user_inactive")
return TokenUser(token=validated_token)
Мои вопросы:
Безопасен ли этот подход? :
- Подключаясь динамически к клиентским базам данных, подвергаю ли я себя каким-либо значительным рискам безопасности?
- Как я могу гарантировать, что строка подключения не будет подделана в токене?
Обработка верификации пользователя:
- В настоящее время я строго проверяю
employee_id
и активный статус пользователя. Есть ли безопасный способ обойти или изменить эту проверку при необходимости? - Каким передовым методам следует следовать для безопасного управления идентификацией пользователей в нескольких базах данных?
- В настоящее время я строго проверяю
Альтернативные подходы:
- Существуют ли альтернативные методы обработки аутентификации, когда таблица пользователей находится не в центральной базе данных, а распределена по динамическим, специфическим для клиента базам данных?
- Может ли использование архитектуры микросервисов с выделенным сервисом аутентификации быть лучшим подходом?
Дополнительная информация:
- Django Version: 3.x
- База данных: MSSQL (используется
pymssql
для соединений) - Аутентификация: JWT (с помощью REST-фреймворка Django)
Я открыт для предложений или лучших практик, которые могут сделать эту настройку более безопасной и эффективной. Заранее спасибо!
Я хочу построить систему аутентификации, которая удовлетворит мою ситуацию, когда нет одной центральной базы данных, а есть несколько клиентских баз данных на сервере