websocket self.scope ['user']在Django通道中一直显示为匿名用户

w8biq8rn  于 2023-10-20  发布在  Go
关注(0)|答案(5)|浏览(131)

当我登录到我的前端时,我在django channels中的www.example.com中的self.scope 'user ']调用friends.consumer.py将返回AnkaryousUser,但当登录并调用我在www.example.com中的self.scope 'user']chat.consumer.py,它将显示为登录的用户。由于某种原因,我的一个应用程序中的作用域“用户”可以工作,而另一个不能。我不明白有什么问题。我在我的Django项目中设置了如下路由:
routing.py

from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import chat.routing
import friends.routing

application = ProtocolTypeRouter ({
    'websocket': AuthMiddlewareStack(
        URLRouter(
        friends.routing.websocket_urlpatterns + chat.routing.websocket_urlpatterns
        )
    )
})

我的第二个www.example.com的结构consumer.py与第一个consumer.py类似。这是我的consumer.py,其中作用域['user']工作(在第一个消费者中我不需要作用域['user'],但我只是想测试它是否工作
chat.consumer.py

class ChatConsumer(WebsocketConsumer):
  ...
   def connect(self):
    print(self.scope['user'])
    self.room_name = self.scope['url_route']['kwargs']['room_name']
    self.room_group_name = 'chat_%s' % self.room_name

    # Join room group
    async_to_sync (self.channel_layer.group_add)(
        self.room_group_name,
        self.channel_name
    )

    self.accept()

这段代码是消费者,即使在我登录后,我的作用域[“user”]也显示为匿名用户。
friends.consumers.py

class FriendRequestConsumer(JsonWebsocketConsumer):
    def connect(self):
        user = self.scope['user']
        grp = 'notifications_{}'.format(user.username)
        self.accept()
        async_to_sync(self.channel_layer.group_add(grp, self.channel_name))

这里也是我的routing.py为每个应用程序
friends.routing.py

from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    re_path(r'^ws/friend-request-notification/$', consumers.FriendRequestConsumer),
]

chat.routing.py

from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer),
]

我能够在我的reactjs前端连接到它们的WebSocket。我知道AuthMiddlewareStack允许我们拉范围['user'],我只是不明白为什么一个工作,一个做。可能是我没有在前端正确连接到WebSocket,或者我在某个消费者身上缺少了什么?我很感激你的帮助,并提前表示感谢。
为了在我的js中连接到WebSocket,我创建了一个chat.js文件和一个notifications.js
chat.js

class Chat extends React.Component{
  ... 
   initialiseChat() {
this.waitForSocketConnection(()=> {
  WebSocketInstance.fetchMessages(
    this.props.username,
    this.props.match.params.id
   )
  })
WebSocketInstance.connect(this.props.match.params.id)
}
constructor(props){
  super(props)
  this.initialiseChat()
}

notifications.js

class Notifications extends React.Component{
   ...
  initialiseNotification(){
  this.waitForSocketConnection(() => {
    NotificationWebSocketInstance.fetchFriendRequests(
     this.props.id
  )
  })
  NotificationWebSocketInstance.connect()
}

constructor(props){
  super(props)
  this.initialiseNotification()
}

以下是我的WebSocket操作:
webosocket.js(此连接函数在chat.js中调用)

class WebSocketService {
  ...
  connect(chatUrl) {
const path ='ws://127.0.0.1:8000/ws/chat/'+chatUrl+'/';
console.log(path)
this.socketRef = new WebSocket(path)
this.socketRef.onopen = () => {
  console.log('websocket open')

}
...
const WebSocketInstance = WebSocketService.getInstance();
export default WebSocketInstance;

下面是notification.js的WebSocket
notificationWebsocket.js

class WebSocketNotifications {
 ...
 connect(){
 const path = 'ws://127.0.0.1:8000/ws/friend-request-notification/'
 console.log(path)
 this.socketRef = new WebSocket(path)
 this.socketRef.onopen = () =>{
   console.log('websocket open')
 }
 ...
 const NotificationWebSocketInstance = 
  WebSocketNotifications.getInstance();

 export default NotificationWebSocketInstance;

这里是routes.js

class BaseRouter extends React.Component {
  <Route exact path = '/chat/:id' render={(props) => <Chat {...props} 
      {...this.props} isAuthenticated={this.props.isAuthenticated} />}  
      />
    <Route exact path = '/notifications/' render={(props) => 
       <Notifications {...props} {...this.props} isAuthenticated= 
       {this.props.isAuthenticated} />}  />
nx7onnlm

nx7onnlm1#

您可以看到这两个re_path之间

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer),
]

你用(?P<room_name>\w+)作为聊天消费者。

websocket_urlpatterns = [
    re_path(r'^ws/friend-request-notification/$', consumers.FriendRequestConsumer),
]

但在FriendRequestConsumer的情况下,你没有使用。在我的情况下,我有同样的问题,我已经添加了一个房间名称没有理由,可以通过任何字符串在该房间名称。但无论如何,我现在可以访问self.scope['user']
我的asgi.py是这样的

ws_patterns=[
    re_path(r'ws/notification/(?P<room_name>\w+)/$', NotificationConsumer.as_asgi()) # NEW CHANGE
    # path('ws/notification/', NotificationConsumer.as_asgi()), # as_PREVIOUS
]
application=ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter(ws_patterns)
        ),
    ),
})
sg3maiej

sg3maiej2#

您的令牌中间件一定存在一些问题

qmb5sa22

qmb5sa223#

虽然在这种情况下这可能不是问题的根源,但这可能有助于像我这样偶然发现这个问题的人。
我的令牌认证系统使用django_rest_knox,认证和登录过程一直运行良好,直到尝试访问self.scope['user']中的user值,返回AncourageousUser。
事实证明,这就像从django添加登录方法一样简单。

# api.py

    from django.contrib.auth import login

    class LoginAPI(generics.GenericAPIView):
        permission_classes = (permissions.AllowAny, )
        serializer_class = LoginSerializer

        def post(self, request, *args, **kwargs):

            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            user = serializer.validated_data
            login(request, user) # <- This was missing
            return Response({
                "user": UserSerializer(user, 
            context=self.get_serializer_context()).data,
                "token": AuthToken.objects.create(user)[1]
            })
dgiusagp

dgiusagp4#

consumers.FriendRequestConsumer.as_asgi()
必须
WebSocket_urlpatterns = [ re_path(r'^ws/friend-request-notification/$',consumers.FriendRequestConsumer.as_asgi()),]

a8jjtwal

a8jjtwal5#

在脚本中使用此websoket路径:

const ws = new WebSocket(
            'ws://'
            + window.location.host
            + '/ws'
            + window.location.pathname);

相关问题