django 使用channels 搭建websocket聊天程序

news2024/9/27 19:15:16

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

 效果如下:

 主要实现功能

基于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权限管理系统

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/712289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数字经济时代,高校该如何建设大数据实验实训室,培养高质量数智人才?

数智人才作为数字经济时代发展的重要支撑资源,人才质量、存量与储备量之争,成为综合国力和区位竞争的重要内容,而大数据与人工智能技术作为数字经济的主要驱动力,相关人才的培养尤其重要。教育部自2016年起,陆续批准设…

Maven中 排除依赖 exclusions

使用maven进行jar包依赖管理时&#xff0c;maven会自行管理jar包及其依赖链条&#xff0c;但往往会遇到依赖冲突问题&#xff0c;这时候就可以尝试使用exclusions来进行依赖管理 demo:排除tomcat 启用 jetty <dependency><groupId>org.springframework.boot</g…

map父子维护的ebom父子部件关系计算组套数量

map父子维护的ebom父子部件关系计算组套数量 使用ebom时候&#xff0c;把部件父子关系和安装数量维护在了map上面&#xff0c;要计算组套数量&#xff0c;需要递归从当前往上取出父级安装数量相乘&#xff0c;一直取到最顶层。 G的组套数量&#xff1a;GDB32212 E的组套数量&a…

如何提高应用的用户留存

用户的留存率是我们应用内最重要的指标之一&#xff0c;是指有多少人在一段时间后还在使用该应用&#xff0c;它定义了我们的受众规模&#xff0c;让我们知道应用是否有增长的能力。 提高应用保留率的策略&#xff1a;1&#xff0c;推送通知&#xff0c;在适当的时候发送推送通…

计算机网络速成

更好的阅读体验 \color{red}{\huge{更好的阅读体验}} 更好的阅读体验 因特网概述 网络、互联网和因特网 网络&#xff1a;将多个计算机或计算机网络通过通信线路连接起来&#xff0c;使得它们可以相互通信和交换信息的系统。由若干节点&#xff08;Node&#xff09;和连接这些…

LInux:生成崩溃程序的core文件

core文件是linux系统下一种记录软件异常的机制&#xff0c;在进程运行崩溃时&#xff0c;系统会将coredump信息写入core文件。 这样就方便我们定位软件问题。 1. 设置core文件大小 使用ulimit -c可以查看当前core文件的大小 默认情况下&#xff0c;core文件的大小为0&#xf…

chatgpt赋能python:Python开发的SEO应用

Python开发的SEO应用 搜索引擎优化&#xff08;SEO&#xff09;已经成为每个网站所有者需要考虑的重要因素之一。随着搜索引擎算法的不断变化和演进&#xff0c;我们需要确保我们的网站能在各种搜索引擎中进行良好的排名。Python作为一门强大的编程语言&#xff0c;已经被广泛…

Databend v1.2 版本发布!Data + AI

各位社区小伙伴们&#xff0c;Databend 于 2023 年 6 月 29 日迎来了 v1.2.0 版本的正式发布&#xff01;相较于 v1.1.0 版本&#xff0c;开发者们一共新增了 600 次 commit&#xff0c;涉及 3083 个文件变更&#xff0c;约 17 万 行代码修改。感谢各位社区伙伴的参与&#xff…

跨境电商如何快速提升产品排名和转化率,打造爆款产品

中小卖家在跨境电商平台上经营时&#xff0c;经常会遇到提升销售瓶颈的问题。今天陈哥将分享一个快速打造爆款的方法&#xff0c;除了SEO优化&#xff08;关键词分析、优化标题、图片、产品描述和定价&#xff09;等方面的策略。同时&#xff0c;测评也是一个有效的手段&#x…

规则引擎是什么,常见的应用领域,你知道吗?

规则引擎是什么 规则引擎&#xff0c;规则引擎是企业数字化转型升级过程中非常必要的软件工具&#xff0c;是一种能够自动执行一定条件下的预设逻辑的技术&#xff0c;可以帮助企业在收到数据或事件时自动触发相关业务规则&#xff0c;其主要优势如下&#xff1a; 易于维护与…

2023年华中杯数学建模C题空气质量预测与预警解题全过程文档及程序

2023年华中杯数学建模 C题 空气质量预测与预警 原题再现 空气污染对人类健康、生态环境、社会经济造成危害&#xff0c;其污染水平受诸多因素的影响&#xff0c;如 PM2.5、PM10、CO、气温、风速、降水量等&#xff0c;探究 PM2.5 等污染物浓度的因素&#xff0c;更精准的预测…

山西电力市场日前价格预测【2023-07-04】

日前价格预测 预测明日&#xff08;2023-07-04&#xff09;山西电力市场全天平均日前电价为136.03元/MWh。其中&#xff0c;最高日前电价为280.29元/MWh&#xff0c;预计出现在00:15。最低日前电价为0.00元/MWh&#xff0c;预计出现在09:15-18:15。 以上预测仅供学习参考&…

速成!|量子粒子群优化算法及其实现(Matlab)

作者在前面的两篇文章中介绍了标准粒子群及其变体&#xff0c;**由于PSO算法需要设定的参数(惯性因子w&#xff0c;学习因子 c1&#xff0c;c2)太多&#xff0c;不利于找到待优化模型的最优参数&#xff0c;而且粒子位置变化缺少随机性&#xff0c;容易陷入局部最优。**针对这些…

花了 44 块钱,实现 Java 发送短信功能

个人项目&#xff1a;社交支付项目&#xff08;小老板&#xff09; 作者&#xff1a;三哥&#xff08;https://j3cod3.cn&#xff09; 本篇为从 0 到 1 的一个&#xff0c;用 Java 对接腾讯短信发送功能的一篇流程文章。而标题中的 44 大洋则是用来购买短信套餐&#xff0c;当然…

怎么用21zui工具为图片添加水印

有些小伙伴工作内容是推荐公司产品&#xff0c;在平台中发布产品图片的时候&#xff0c;应该为图片添加专属水印&#xff08;文字水印或者logo水印&#xff09;&#xff0c;为什么要这么做呢&#xff1f;因为添加水印可以保护我们的图片不被盗用&#xff0c;同时也有助于推广我…

(24)目标检测算法之YOLOv6 (2)量化与部署详解

目标检测算法之YOLOv6 (2)量化与部署详解 详解量化训练方式 详解部署方法&#xff1a;onnx 、openvnio、 tensorrt YLOLOv6目前发布的模型&#xff1a;从模型大小方面来看&#xff0c;可分为微小型(Nano)&#xff0c;小(Small)&#xff0c;中(Medium)&#xff0c;大模型(Larg…

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器

前言&#xff1a;本章内容主要是演示在vivado下利用Verilog语言进行单周期简易CPU的设计。一步一步自己实现模型机的设计。本章先介绍单周期简易CPU中基本时序逻辑部件设计。 &#x1f4bb;环境&#xff1a;一台内存4GB以上&#xff0c;装有64位Windows操作系统和Vivado 2017.…

黑马微信小程序登录弹窗问题与解决的说明

1.问题 1.1开发者工具报错 [getFuzzyLocation] is not authorized如何解决&#xff1f; 1.2弹窗问题 2.解决方法 2.1开发工具报错问题 首先登录微信公众平台&#xff0c;找到开发管理。如下图 然后开通wx.getFuzzyLocation 申请模版&#xff0c;通过速度很多&#xff0c;…

24小时不定时价格监测如何做到

在做电商平台的数据监测时&#xff0c;品牌需要对线上监测的数据进行不定时监测&#xff0c;这是因为品牌做价格监测的目的是为了管控渠道&#xff0c;如果对店铺只能在特定的时间进行监测&#xff0c;那对于其他时间段的低价行为将不被发现&#xff0c;这也会使品牌渠道管控的…

【Redis】配置

&#x1f3af;Redis 配置 Redis 的配置文件位于 Redis 安装目录下&#xff0c;文件名为 redis.conf(Windows 名为 redis.windows.conf)。 1、查看配置 语法如下通过 config get 命令查看或设置配置项。 CONFIG GET 配置的名字 使用 * 号获取所有配置项 127.0.0.1:6379>…