Допустим, у меня есть SaaS на основе бэкэнда Django, который обрабатывает данные пользователей и записывает все в Elasticsearch.Теперь я хотел бы предоставить пользователям доступ к поиску и запрашивать их данные, хранящиеся в ES, используя все возможные поисковые запросы, доступные в ES.Очевидно, что пользователь должен иметь доступ только к своим данным, а не к данным других пользователей.Я знаю, что это можно сделать разными способами, но мне интересно, что является безопасным и лучшим решением?На данный момент я храню все в одном индексе и набираю, как показано ниже, но я могу сделать это любым способом.
"_index": "example_index",
"_type": "example_type",
"_id": "H2s-lGsdshEzmewdKtL",
"_score": 1,
"_source": {
"user_id": 1,
"field1": "example1",
"field2": "example2",
"field3": "example3"
}
Я думаю, что лучшим способом было бы связать каждый документ с user_id.Пользователь отправит, например, запрос GET с телом и заголовок авторизации с токеном.Я бы использовал Token для извлечения идентификатора пользователя, например, таким образом
key = request.META.get('HTTP_AUTHORIZATION').split()[1]
user_id = Token.objects.get(key=key).user_id
. После этого я перенаправил бы его запрос в ES, и были бы возвращены только те данные, которые соответствуют требованиям и принадлежат этому пользователю.Конечно, я мог бы сделать это, как показано выше, где я также добавил поле user_id
.Например, я мог бы использовать post_filter таким образом:
К каждому запросу я бы добавил что-то вроде этого:
,
"post_filter": {
"match": {
"user_id": 1
}
}
Например, пользователь отправляет GET с телом
{
"query": {
"regexp": {
"tag": ".*example.*"
}
}
}
, и я изменяю это в своем бэкэнде и перенаправлении на ES с телом:
{
"query": {
"regexp": {
"tag": ".*example.*"
}
},
"post_filter": {
"match": {
"user_id": 1
}
}
}
, но мне не кажется, что включение этого поля в _source
являетсяотличная идея.Я почти уверен, что это может быть решено более оптимальным способом, чем post_filtering
.Я вижу много информации об авторизации в ES, но не могу найти, как связать документ с user_id
, а затем искать только его документы без post_filtering
.Любые идеи?
ОБНОВЛЕНИЕ
Мое текущее решение выглядит так, как показано ниже, однако, как я уже говорил, я считаю, что это не оптимальный путь. Если у кого-то есть идея, как мне решить эту проблему описанным выше способом, я буду благодарен за помощь.
Я отправляю, например,
{
"query": {
"regexp": {
"tag": ".*test.*"
}
}
}
В бэкэнде DjangoЯ просто делаю
key = request.META.get('HTTP_AUTHORIZATION').split()[1]
user_id = Token.objects.get(key=key).user_id
body = json.loads(request.body)
body['post_filter'] = {"match": {"user_id": user_id}}
res = es.search(index="pictures", doc_type="picture", body=body)
output = []
for hit in res['hits']['hits']:
output.append(hit["_source"])
return Response(
{'output': output},
status=status.HTTP_200_OK)