Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Django';s与Django通道的会话身份验证?_Django_Reactjs_Authentication_Websocket_Django Channels - Fatal编程技术网

如何使用Django';s与Django通道的会话身份验证?

如何使用Django';s与Django通道的会话身份验证?,django,reactjs,authentication,websocket,django-channels,Django,Reactjs,Authentication,Websocket,Django Channels,我正在使用Django、Django频道和React开发一个国际象棋web应用程序。我正在使用WebSocket进行在线玩家之间的游戏,以及更新哪些玩家现在在线并且可以玩。但是,我在身份验证方面遇到了困难。我首先从令牌身份验证开始,但我发现不可能在websocket请求中发送带有令牌的自定义头。然后我回到默认的django.contrib.auth会话身份验证。不幸的是,当客户端登录并连接到websocket时,我无法获取他们的用户信息,就好像用户正在使用与websocket不同的会话一样。在w

我正在使用Django、Django频道和React开发一个国际象棋web应用程序。我正在使用WebSocket进行在线玩家之间的游戏,以及更新哪些玩家现在在线并且可以玩。但是,我在身份验证方面遇到了困难。我首先从令牌身份验证开始,但我发现不可能在websocket请求中发送带有令牌的自定义头。然后我回到默认的django.contrib.auth会话身份验证。不幸的是,当客户端登录并连接到websocket时,我无法获取他们的用户信息,就好像用户正在使用与websocket不同的会话一样。在websocket consumers中打印self.scope[“user”]时,我得到值AnonymousUser。请注意,我可以使用websocket交换消息,身份验证可以很好地处理普通http请求,因为我可以防止未登录的用户访问视图

我猜问题与客户端的websocket请求不像http请求那样访问或使用cookie进行身份验证有关

有没有人遇到过类似的问题?他们是如何解决的

以下是我在react中发送websocket消息的方式:

submitMessage = (evt) => {
    //console.log("token in Messenger=",this.props.token);
    evt.preventDefault();
    const message = { message: this.state.message_to_send}
    this.ws.send(JSON.stringify(message))
  }
这是用于处理websocket请求的后端代码:

from channels.generic.websocket import WebsocketConsumer
import json
from asgiref.sync import async_to_sync

class LoggedUsersConsumer(WebsocketConsumer):
    def connect(self):
        self.user = self.scope["user"]
        print(self.scope)
        print(self.user,"+++++++++++++")
        #Join group
        async_to_sync(self.channel_layer.group_add)(
            "logged_users",
            self.channel_name
        )
        self.accept()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            "logged_users",
            self.channel_name
        )

    def receive(self, text_data):
        self.user = self.scope["user"]
        print(self.user,"+++++++++++++")

        text_data_json = json.loads(text_data)
        print(text_data_json)
        message = text_data_json['message']

        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            "logged_users",
            {
                'type': 'logged_user_message',
                'message': message
            }
        )

    def logged_user_message(self, event):
        message = event['message']

        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'message': message
        }))

我认为你是对的,你可能没有用于客户端请求的会话cookie,这就是为什么你得到了匿名用户。我认为这与您在React和Django中处理websocket请求的方式无关

请在React前端检查浏览器的cookie(通过Chrome/Firefox中的开发者工具)。您应该至少有2个cookie、csrftoken和sessionid。如果其中任何一项都不具备,以下内容可能会帮助您朝着正确的方向前进。在使用Vue、Django通道和Django Rest框架进行开发时,我也经历了同样的经历

如果您通过浏览器访问Django后端,HTML模板和浏览器将负责设置cookie。从React或Vue执行此操作时,不会呈现HTML。因此,您需要自己实现身份验证和cookie设置。当然,您需要在稍后用于访问web套接字的同一会话中从React进行身份验证

我使用以下Django视图从前端进行身份验证:

@api_view()
@permission_classes([AllowAny])
@ensure_csrf_cookie
@csrf_exempt
def session_info(request):
    """
    View to retrieve user info for current user. (Can be adapted to your needs). If user is not logged in, view will
    still return CSRF cookie which in neccessary for authentication.
    """
    if not request.user.is_authenticated:
        return Response({"message": "Not authenticated.", "authenticated": False})
    return Response(
        {"message": "Authenticated.", "authenticated": True, "user": str(request.user)}
    )


@api_view(['POST'])
@permission_classes([AllowAny])
def session_auth(request):
    """
    Login-view.
    """
    username = request.data['username']
    password = request.data['password']
    user = authenticate(request, username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
            request.session['authenticated_user'] = user.username
            return Response(
                {
                    "message": "Authenticated.",
                    "authenticated": True,
                    "name": user.name,
                }
            )
    return Response({"message": "Not authenticated", "authenticated": False})


在URL.py中,您需要添加以下内容:

urlpatterns = [
    path(
        'session/',
        views.session_info,
        name='session',
    ),
    path(
        'sessionauth/',
        views.session_auth,
        name='sessionauth',
    ),
]
现在,您可以从前端执行类似的操作(以下是我的javascript/Vue代码,稍微适合于本文,但您可能可以使用React执行类似的操作):


我希望这能有所帮助。如果没有,请告诉我。

我认为您是对的,您可能没有用于客户端请求的会话cookie,这就是您获得匿名用户的原因。我认为这与您在React和Django中处理websocket请求的方式无关

请在React前端检查浏览器的cookie(通过Chrome/Firefox中的开发者工具)。您应该至少有2个cookie、csrftoken和sessionid。如果其中任何一项都不具备,以下内容可能会帮助您朝着正确的方向前进。在使用Vue、Django通道和Django Rest框架进行开发时,我也经历了同样的经历

如果您通过浏览器访问Django后端,HTML模板和浏览器将负责设置cookie。从React或Vue执行此操作时,不会呈现HTML。因此,您需要自己实现身份验证和cookie设置。当然,您需要在稍后用于访问web套接字的同一会话中从React进行身份验证

我使用以下Django视图从前端进行身份验证:

@api_view()
@permission_classes([AllowAny])
@ensure_csrf_cookie
@csrf_exempt
def session_info(request):
    """
    View to retrieve user info for current user. (Can be adapted to your needs). If user is not logged in, view will
    still return CSRF cookie which in neccessary for authentication.
    """
    if not request.user.is_authenticated:
        return Response({"message": "Not authenticated.", "authenticated": False})
    return Response(
        {"message": "Authenticated.", "authenticated": True, "user": str(request.user)}
    )


@api_view(['POST'])
@permission_classes([AllowAny])
def session_auth(request):
    """
    Login-view.
    """
    username = request.data['username']
    password = request.data['password']
    user = authenticate(request, username=username, password=password)
    if user is not None:
        if user.is_active:
            login(request, user)
            request.session['authenticated_user'] = user.username
            return Response(
                {
                    "message": "Authenticated.",
                    "authenticated": True,
                    "name": user.name,
                }
            )
    return Response({"message": "Not authenticated", "authenticated": False})


在URL.py中,您需要添加以下内容:

urlpatterns = [
    path(
        'session/',
        views.session_info,
        name='session',
    ),
    path(
        'sessionauth/',
        views.session_auth,
        name='sessionauth',
    ),
]
现在,您可以从前端执行类似的操作(以下是我的javascript/Vue代码,稍微适合于本文,但您可能可以使用React执行类似的操作):

我希望这能有所帮助。如果没有,请告诉我