Итак, я закончил так:

ользую интерфейс внешнего интерфейса (Vuejs) а такжеДжанго-отдых-рамка для REST API в моем проекте. Кроме того, для аутентификации веб-токена JSON я используюДжанго-отдых-каркасного JWT, После успешного входа в систему пользователю предоставляется токен. Этот токен передается в каждый запрос для извлечения любого материала, связанного с API.

Теперь я хотел бы интегрироватьДжанго каналы в мой проект. Итак, после успешного входа в систему, когда токен получен на стороне клиента, я хотел бы установить соединение через веб-сокет. Затем на сервере (потребитель) я хотел бы проверить, не является ли запрашиваемый пользователь анонимным. Если запрашиваемый пользователь является анонимным, я хотел бы закрыть соединение или принять его.

Вот как у меня до сих пор:

сторона клиента:

const socket = new WebSocket("ws://" + "dev.site.com"+ "/chat/");

routing.py:

channel_routing = [
    route("websocket.connect", ws_connect),
    ...
    ...
]

потребители:

def ws_connect(message):

    # if the user is no anonymous
    message.reply_channel.send({
        "accept": True
    })

    # else
    message.reply_channel.send({
        "close": True
    })

вдокументация есть декоратор@channel_session_user_from_http который обеспечитmessage.user, Но я использую токен вместо сессии. Как я могу проверить пользователя на соединение при использовании токена аутентификации, чтобы я мог принять или закрыть соединение. Или, если есть лучший способ, пожалуйста, сообщите мне об этом. Спасибо.

Ответы на вопрос(2)

тентификации пользователя.

Что делать с токеном?

Вы можете передать токен в виде строки запроса и получить параметры запроса. Узнайте больше о том, как получить параметры запросаВот.Или, если вы уже передаете его в заголовке авторизации запроса, вы можете получить его оттуда, как @hoefling сделал с его ответом. Помните, чтобы сначала подделать эту просьбу.

Как проверить этот токен и получить пользователя?

в заключениеVerifyJSONWebTokenSerializer класс - это все, что мне нужно для проверки токена и получения объекта пользователя этого токена. (Спасибо @hoefling!) Вы можете прочитать фактический код django-rest-framework-jwtВот.

Итак, я закончил так:

def ws_connect(message):
    message.content.setdefault('method', 'FAKE')
    django_request = AsgiRequest(message)
    token = django_request.GET['token'].split(' ')[1]
    try:
        data = {'token': token}
        valid_data = VerifyJSONWebTokenSerializer().validate(data)
        user = valid_data['user']
        ...
        ...
        message.reply_channel.send({
            "accept": True
        })
    except (KeyError, InvalidTokenError, ValidationError,):
        ...
        ...
        message.reply_channel.send({
            "text": "Authentication error",
            "close": True
        })
Решение Вопроса

что браузеры не поддерживают передачу заголовков аутентификации jwt при обновлении websocket, так что это в основном так. Я столкнулся с этой проблемой некоторое время назад и нашел решение передать токен через параметры запроса - обратите внимание, чтоэто совершенно небезопасно без TLS как вы выставляете аутентификацию в URI. У меня больше нет доступа к точному коду, но вот идея:

from channels.generic.websockets import JsonWebsocketConsumer
from channels.handler import AsgiRequest

from rest_framework_jwt.serializers import VerifyJSONWebTokenSerializer
from jwt.exceptions import InvalidTokenError
from rest_framework.exceptions import ValidationError

class Consumer(JsonWebsocketConsumer):

    def connect(self, message, **kwargs):
        # construct a fake http-like request object from the message
        message.content.setdefault('method', 'FAKE')
        request = AsgiRequest(message)
        # validate the token
        try:
            VerifyJSONWebTokenSerializer().validate(request.GET)
            super().connect(message, **kwargs)
        except (KeyError, InvalidTokenError, ValidationError,):
            # token is either not available or invalid
            # so we disconnect the user
            message.reply_channel.send({'close': True})

Зарегистрировать потребителя с

channel_routing = [
    ...
    route_class(Consumer, path=r'^my-ws-endpoint

На стороне браузера вы можете установить соединение с websocket, передав токен в качестве параметра запроса в URI websocket:

let token: string = 'my-token'; // get the token
let wsHandler: $WebSocket = new $WebSocket('wss://example.com/my-ws-endpoint/?token=' + token, ...);

Затем вы можете извлечь код проверки подлинности в декораторе, аналогичном@channel_session_user_from_http и просто украсьте свои процедуры подключения или извлеките код в миксины, если вы используете маршруты на основе классов.

Я хотел бы повторить, однако, что этот подход совершенно небезопасен без использования шифрования, поэтому в производстве ваши URI должны начинаться сhttps/wss.

редактировать: вотдовольно хорошее решение для аутентификации токена DRF, подходит как для маршрутов на основе функций, так и на основе классов. У него почти такой же подход, как и у меня, создание объекта запроса и передача его аутентификатору.

), ]

На стороне браузера вы можете установить соединение с websocket, передав токен в качестве параметра запроса в URI websocket:

let token: string = 'my-token'; // get the token
let wsHandler: $WebSocket = new $WebSocket('wss://example.com/my-ws-endpoint/?token=' + token, ...);

Затем вы можете извлечь код проверки подлинности в декораторе, аналогичном@channel_session_user_from_http и просто украсьте свои процедуры подключения или извлеките код в миксины, если вы используете маршруты на основе классов.

Я хотел бы повторить, однако, что этот подход совершенно небезопасен без использования шифрования, поэтому в производстве ваши URI должны начинаться сhttps/wss.

редактировать: вотдовольно хорошее решение для аутентификации токена DRF, подходит как для маршрутов на основе функций, так и на основе классов. У него почти такой же подход, как и у меня, создание объекта запроса и передача его аутентификатору.

 hoefling29 янв. 2018 г., 14:39
@injaon ваш токен аутентификации предоставляется без шифрования, например, в случае атаки MITM.
 hoefling17 сент. 2017 г., 11:53
Рад, что смог помочь!
 injaon29 янв. 2018 г., 14:28
https / wss выставить через URI?
 Robin16 сент. 2017 г., 21:01
Большой! Ваш ответ мне очень помог! Спасибо.

Ваш ответ на вопрос