django 使用channels 搭建websocket聊天程序

这篇具有很好参考价值的文章主要介绍了django 使用channels 搭建websocket聊天程序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 channels官方文档:Django Channels — Channels 4.0.0 documentation

 效果如下:

django 使用channels 搭建websocket聊天程序,Xadmin,Django,容器,django,websocket,python,redis,jwt认证

 主要实现功能

基于Django的认证的群聊

具体实现

当建立websocket的时候,建立之前是http消息,我们可以拿到http消息里面的cookie等信息进行认证,本次使用的是jwt认证,因此需要在建立的连接的时候,将jwt认证信息通过cookie发送给后端,进行通信认证,具体方法如下:

from rest_framework_simplejwt.tokens import AccessToken
from django.http.cookie import parse_cookie
from rest_framework_simplejwt.authentication import JWTAuthentication

class ServerAccessToken(AccessToken):
    """
    自定义的token方法是为了登出的时候,将 access token 禁用
    """

    def verify(self):
        user_id = self.payload.get('user_id')
        if BlackAccessTokenCache(user_id, hashlib.md5(self.token).hexdigest()).get_storage_cache():
            raise TokenError('Token is invalid or expired')
        super().verify()


class CookieJWTAuthentication(JWTAuthentication):
    """
    支持cookie认证,是为了可以访问 django-proxy 的页面,比如 flower
    """

    def get_header(self, request):
        header = super().get_header(request)
        if not header:
            cookies = request.META.get('HTTP_COOKIE')
            if cookies:
                cookie_dict = parse_cookie(cookies)
                header = f"Bearer {cookie_dict.get('X-Token')}".encode('utf-8')
        return header



async def token_auth(scope):
    cookies = scope.get('cookies')
    if cookies:
        token = f"{cookies.get('X-Token')}".encode('utf-8')
        if token:
            try:

                auth_class = CookieJWTAuthentication()
                validated_token = ServerAccessToken(token)
                return True, await sync_to_async(auth_class.get_user)(validated_token)
            except TokenError as e:
                return False, e.args[0]
    return False, False

然后再建立连接的时候,进行一个认证

class MessageNotify(AsyncJsonWebsocketConsumer):
    def __init__(self, *args, **kwargs):
        super().__init__(args, kwargs)
        self.room_group_name = None
        self.disconnected = True
        self.username = ""

    async def connect(self):
        status, user_obj = await token_auth(self.scope)
        if not status:
            logger.error(f"auth failed {user_obj}")
            # https://developer.mozilla.org/zh-CN/docs/Web/API/CloseEvent#status_codes
            await self.close(4401)

具体群聊核心代码如下:

class MessageNotify(AsyncJsonWebsocketConsumer):
    def __init__(self, *args, **kwargs):
        super().__init__(args, kwargs)
        self.room_group_name = None
        self.disconnected = True
        self.username = ""

    async def connect(self):
        status, user_obj = await token_auth(self.scope)
        if not status:
            logger.error(f"auth failed {user_obj}")
            # https://developer.mozilla.org/zh-CN/docs/Web/API/CloseEvent#status_codes
            await self.close(4401)
        else:
            logger.info(f"{user_obj} connect success")
            room_name = self.scope["url_route"]["kwargs"].get('room_name')
            username = self.scope["url_route"]["kwargs"].get('username')
            # data = verify_token(token, room_name, success_once=True)
            if username and room_name:
                self.disconnected = False
                self.username = username
                self.room_group_name = f"message_{room_name}"
                # Join room group
                await self.channel_layer.group_add(self.room_group_name, self.channel_name)
                await self.accept()
            else:
                logger.error(f"room_name:{room_name} token:{username} auth failed")
                await self.close()

    async def disconnect(self, close_code):
        self.disconnected = True
        if self.room_group_name:
            await self.channel_layer.group_discard(self.room_group_name, self.channel_name)

    # Receive message from WebSocket
    async def receive_json(self, content, **kwargs):
        action = content.get('action')
        if not action:
            await self.close()
        data = content.get('data', {})
        if action == "message":
            data['uid'] = self.channel_name
            data['username'] = self.username
            # Send message to room group
            await self.channel_layer.group_send(
                self.room_group_name, {"type": "chat_message", "data": data}
            )
        else:
            await self.channel_layer.send(self.channel_name, {"type": action, "data": data})

    async def userinfo(self, event):
        data = {
            'username': self.username,
            'uid': self.channel_name
        }
        await self.send_data('userinfo', {'data': data})

    async def chat_message(self, event):
        data = event["data"]
        data['time'] = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
        # Send message to WebSocket
        await self.send_data('message', {'data': data})

    async def send_data(self, action, content, close=False):
        data = {
            'time': time.time(),
            'action': action
        }
        data.update(content)
        return await super().send_json(data, close)

中间还涉及消息队列,本次使用的是基于redis的消息队列,需要在settings.py进行配置

CHANNEL_LAYERS = {
    "default": {
        # "BACKEND": "channels_redis.core.RedisChannelLayer",
        "BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer",
        "CONFIG": {
            "hosts": [f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}/{CHANNEL_LAYERS_CACHE_ID}"],
        },
    },
}

代码已经开源,GitHub地址:GitHub - nineaiyu/xadmin-server: xadmin-基于Django+vue3的rbac权限管理系统

 文章来源地址https://www.toymoban.com/news/detail-530902.html

到了这里,关于django 使用channels 搭建websocket聊天程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Django】Django4.1.2使用xadmin避坑指南

    换成Django4版本使用xadmin真是需要巨大勇气。 win10 python3.9.0 django4.1.2 解决办法: 如果正常安装了xadmin库的话,six库也会安装,把 项目根目录/venv/Lib/site-packages/six.py 复制到 项目根目录/venv/Lib/site-packages/django/utils 下即可。 分析: Django已经弃用 ugettext(), ugettext_lazy(), ugettext_noo

    2023年04月08日
    浏览(30)
  • 【Django】使用xadmin构建后台管理系统

    在github搜索xadmin并下载源码 由于xadmin报错实在是太多了,我前前后后改了三十多个报错,查阅了数百篇博客以及文献。为了以后不去重复处理报错,我fork了原来的xadmin项目,新建了自己的xadmin版本:MyXadmin,因此我建议你使用该仓库的xadmin版本。 在setting的INSTALLED_APPS中添加

    2024年02月09日
    浏览(33)
  • django channels实战(websocket底层原理和案例)

    asgi.py在django项目同名app目录下 django代码总结 报错如下: 1、不要安装最新的版本,建议安装指定版本 pip install -U channels==3.0.2 2、在python .manage.py runserver 0.0.0.0:8080启动的前提下,新开一个cmd窗口,启动daphne服务 1)首先,确保你已经安装了 Daphne。可以使用以下命令安装最新版

    2024年02月14日
    浏览(31)
  • 基于Django Channels框架和JavaScript WebSockets实现 Making a Chat Application With Django Channels and Java

    作者:禅与计算机程序设计艺术 在本文中,我们将建立一个基于Django Channels框架和JavaScript WebSockets库实现的实时聊天系统,这个系统会让用户之间可以进行即时沟通,聊天室功能强大且实用。通过这个项目,你将学习到Django Channels框架的一些特性,并且能够熟练掌握WebSocke

    2024年02月07日
    浏览(32)
  • 3分钟使用 WebSocket 搭建属于自己的聊天室(WebSocket 原理、应用解析)

    在 WebSocket 出现之前,我们想实现实时通信、变更推送、服务端消息推送功能,我们一般的方案是使用 Ajax 短轮询、长轮询两种方式: 比如我们想实现一个服务端数据变更时,立即通知客户端功能,没有 WebSocket 之前我们可能会采用以下两种方案:短轮询或长轮询 上面两种方

    2024年02月03日
    浏览(34)
  • Django实现websocket聊天室

    WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器双向通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变

    2023年04月23日
    浏览(30)
  • django websocket实现聊天室功能

    注意事项channel版本 django2.x 需要匹配安装 channels 2 django3.x 需要匹配安装 channels 3 Django 3.2.4 channels 3.0.3 Django 3.2.* channels 3.0.2 Django4.2 channles==3.0.5 是因为最新版channels默认不带daphne服务器 直接用命令 python manage.py runsever 默认运行的是wsgi ,修改,删除settings中的wsgi,都不能正确运

    2024年01月22日
    浏览(35)
  • Django + Xadmin 数据列表复选框显示为空,怎么修复这个问题?

    先根据报错信息定位到源代码: 在该文件顶部写入: 然后把: 修改为: 如图:

    2024年02月15日
    浏览(31)
  • 微信小程序 WebSocket 通信 —— 在线聊天

             * 源码已经上传到资源处,需要的话点击跳转下载 |  源码下载         在Node栏目就讲到了Socket通信的内容,使用Node实现Socke通信,还使用两个流行的WebSocket 库,ws 和 socket.io,在小程序中的WebSocket接口和HTML5的WebSocket基本相同,可以实现浏览器与服务器之间的

    2024年02月01日
    浏览(38)
  • 微信小程序 | 基于小程序+Java+WebSocket实现实时聊天功能

    此文主要实现在小程序内聊天对话功能,使用Java作为后端语言进行支持,界面友好,开发简单。 2.1、注册微信公众平台账号。 2.2、下载安装IntelliJ IDEA(后端语言开发工具),Mysql数据库,微信Web开发者工具。 1.创建maven project 先创建一个名为SpringBootDemo的项目,选择【New Proje

    2024年02月02日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包