Python Flask и Graphene: неправильный запрос вызывает проблему безопасности - PullRequest
0 голосов
/ 10 ноября 2018

Я работаю над простой системой обмена сообщениями, где два разных пользователя могут отправлять сообщения друг другу. Прямо сейчас каждый пользователь опрашивает сервер, запрашивая новейшие сообщения, используя graphQL.

Проблема в том, что когда один пользователь, пользователь A, отправляет тонну сообщений (запросы мутации graphQL), пока другой пользователь, пользователь B, опрашивает, иногда кажется, что сообщения были отправлены пользователем B.

Я посмотрел глубже и обнаружил, что в тех случаях, когда сообщения были неправильно распределены, запрос на мутацию был обработан с неверным запросом (как указано в контексте), и current_user из flask_login также является неправильным. current_user, кажется, зависит от запроса. Запрос был одним из запросов пользователя B (которые не являются мутациями.)

Я немного проследил это и нашел точку, где заполняется контекст (https://github.com/graphql-python/flask-graphql/blob/master/flask_graphql/graphqlview.py#L42), но было трудно понять, почему он получал неправильный запрос от Flask.

Мое лучшее предположение - что-то происходит со стеком контекста запросов Flask, но его сложно отследить.

Я должен упомянуть, что аутентификация выполняется с использованием заголовка авторизации, и что я попытался найти случай, когда пользователь был неправильно аутентифицирован, но не смог.

Кажется, что это происходит только тогда, когда я запускаю колбу, используя FLASK_ENV=production flask run, и, кажется, исчезает, когда я запускаю ее, используя gunicorn. Тем не менее, это касается того, что аутентификация может быть настолько хрупкой.

Кто-нибудь видел эту проблему раньше? Есть ли в документации Flask что-то, объясняющее эту проблему, почему это происходит, и, что более важно, почему это не произойдет, когда я использую gunicorn?

Соответствующие версии кода:

  • Колба 1.0.2
  • Flask-GraphQL 2.0.0
  • Flask-Login 0.4.1
  • Flask-SQLAlchemy 2.3.2
  • графен 2.1.3
  • графен-sqlalchemy 2.1.0
  • graphql-core 2.1
  • SQLAlchemy 1.2.12

Пример кода:

import graphene as gr
from graphql import GraphQLError
from flask_login import current_user

from ...models import Message
from .shared import MessageNode

class CreateMessage(gr.Mutation):
    """ Send a message to a channel account """

    message = gr.Field(MessageNode)

    class Arguments:
        body = gr.JSONString(required=True)

    @login_required
    def mutate(self, info, body):
        # Make sure that the body is populated with something
        if not (body.get("text") and not body.get("image")) and not (
            not body.get("text") and body.get("image")
        ):
            raise GraphQLError("Body must contain either text or an image")

        new_message = Message(
            body=body,
            sender_account=current_user, # CURRENT USER IS INCORRECT HERE
        )
        db.session.add(new_message)
        db.session.commit()
        return CreateMessage(message=new_message)
...