后端WebSocket异步编程【免费下载链接】channelsDeveloper-friendly asynchrony for Django项目地址https://gitcode.com/gh_mirrors/ch/channels点击查看免费下载本文以 Channels 官方文档 docs/topics/sessions.rst 为核心结合 channels/sessions.py 源码与 tests/test_http.py 等测试讲解如何在 Django Channels 项目中为 HTTP 与 WebSocket 统一启用基于 Cookie 的标准 Django 会话。读完本文你将掌握SessionMiddlewareStack的正确挂载方式、scope[session]的读写方法以及 HTTP 与 WebSocket 两种场景下会话持久化的关键差异与手动保存技巧。会话在 Channels 中如何工作Channels 完整支持 Django 的标准会话机制会话数据通过 HTTP Cookie 在客户端与服务器之间传递并且对 HTTP 和 WebSocket 两类连接都适用。也就是说你在 Django 视图里习惯使用的request.session在 Channels 的 consumer 中可以等价地通过scope[session]访问。不过WebSocket 场景有几个需要留意的差异下文“会话持久化”一节会详细展开会话的装载从 Cookie 解析并载入会话存储与 HTTP 完全一致会话的保存写回存储并刷新 Cookie在 WebSocket 下不会自动发生需要你在代码中显式调用save()/asave()。快速上手在 asgi.py 中挂载 SessionMiddlewareStackSessionMiddleware支持标准 Django 会话。与所有中间件一样它应该包裹在需要把会话信息放进 scope 的 ASGI 应用外层——例如包裹一个URLRouter以作用于整组 consumer或者包裹单个 consumer。关键在于SessionMiddleware依赖CookieMiddleware才能工作。为了方便Channels 提供了同时包含两者的组合体SessionMiddlewareStack。三者都可以从channels.session实际模块为 channels/sessions.py导入。在asgi.py中按如下方式使用from channels.routing import ProtocolTypeRouter, URLRouter from channels.security.websocket import AllowedHostsOriginValidator from channels.sessions import SessionMiddlewareStack from myapp import consumers application ProtocolTypeRouter({ websocket: AllowedHostsOriginValidator( SessionMiddlewareStack( URLRouter([ path(frontend/, consumers.AsyncChatConsumer.as_asgi()), ]) ) ), })上述代码中SessionMiddlewareStack位于URLRouter外层因此会话信息会注入到该路由下所有 consumer 的 scope 中AllowedHostsOriginValidator负责来源校验与会话中间件互不冲突。需要说明的适用范围SessionMiddleware只在 scope 中提供 HTTP headers 的协议上生效——默认情况下是 HTTP 与 WebSocket以及任何把headers放进 scope 的协议。在 consumer 代码中通过self.scope[session]访问会话class ChatConsumer(WebsocketConsumer): def connect(self, event): self.scope[session][seed] random.randint(1, 1000)SessionMiddleware尊重 Django 默认会话框架的全部相关设置例如SESSION_COOKIE_NAME、SESSION_COOKIE_DOMAIN等无需额外适配。从源码看中间件栈CookieMiddleware → SessionMiddleware → 你的应用理解调用链有助于排查问题。看 channels/sessions.py 的源码CookieMiddlewareCookieMiddleware类channels/sessions.py遍历 scope 中的headers找到名为cookie的头用django.http.parse_cookie解析出scope[cookies]格式与 Django 的request.COOKIES一致如果没有 cookie 头则置为空字典。如果 scope 中没有headers键会直接抛出ValueError提示只能用于 HTTP 或 WebSocket 连接。SessionMiddlewarechannels/sessions.py实例化InstanceSessionWrapper调用resolve_session()根据 cookie 中的会话键实例化会话存储然后把包装后的 scope 和 send 交给内层应用。InstanceSessionWrapperchannels/sessions.py这是真正的核心。它读取settings.SESSION_COOKIE_NAME与settings.SESSION_ENGINE通过import_module(...).SessionStore得到存储类把会话放入scope[session]一个LazyObject并重写 send在发送响应时统一执行“保存会话 注入/删除 Cookie”。SessionMiddlewareStack在源码中的定义极简channels/sessions.pydef SessionMiddlewareStack(inner): return CookieMiddleware(SessionMiddleware(inner))即Cookie 中间件在最外层Session 中间件在其内层再往下才是你的应用。若 scope 中已存在session键说明上层已有会话中间件InstanceSessionWrapper会直接透传避免重复激活。会话持久化HTTP 与 WebSocket 的差异这是整个文档中最重要的实践要点两种协议的行为完全不同。HTTP consumer / ASGI 应用自动保存在 HTTP consumer 或普通 ASGI 应用中会话持久化行为与 Django HTTP 视图一致——只要发送的 HTTP 响应状态码不是500会话就会被保存。实现原理InstanceSessionWrapper通过重写http.response.start消息见save_message_types [http.response.start]channels/sessions.py来注入 Cookie 头。判断逻辑channels/sessions.py为if ( message[type] in self.save_message_types and message.get(status, 200) ! 500 and (modified or settings.SESSION_SAVE_EVERY_REQUEST) ): await self.save_session()若SESSION_SAVE_EVERY_REQUEST设为True每次响应都会保存会话并发送 Cookie否则只有在会话被修改session.modified时才保存。WebSocket consumer必须手动保存在 WebSocket consumer 中会话会被装载进 scope但绝不会自动保存。你必须自己调用# 同步写法 scope[session].save() # 异步写法 await scope[session].asave()无论何时需要把会话持久化到会话存储中都要显式调用。如果一直不保存会话在 consumer 内部依然工作正常它作为实例变量保存在内存中但其他连接或 HTTP 视图将看不到这些改动。注意对于长轮询long-pollingHTTP consumer你可能希望在发送响应之前就保存会话改动。若需要这样做请在发送响应前调用scope[session].save()。会话 Cookie 的写入与删除细节CookieMiddleware提供了两个类方法实际处理 Cookie 的序列化与写入set_cookie(message, key, value, ...)channels/sessions.py向 HTTP 响应消息中追加Set-Cookie头。支持的参数如下参数默认值说明max_ageNoneCookie 存活秒数会同时生成max-age与expiresexpiresNone可为格式化字符串、UTC 的 naivedatetime或任意时区的 awaredatetime传 datetime 时自动换算max_agepath/Cookie 路径domainNoneCookie 域secureFalse仅 HTTPS 传输httponlyFalse禁止脚本读取samesitelax必须是strict、lax或none否则断言失败delete_cookie(message, key, ...)channels/sessions.py通过max_age0与过期时间Thu, 01-Jan-1970删除客户端 Cookie。在send重写中保存会话后若检测到会话已空session.is_empty()则删除 Cookie否则根据会话的过期设置生成 Cookie若get_expire_at_browser_close()为真则不设置max_age浏览器关闭即失效否则用get_expiry_age()计算max_age和expires。所有写 Cookie 的参数都取自 Django 设置SESSION_COOKIE_DOMAIN、SESSION_COOKIE_PATH、SESSION_COOKIE_SECURE、SESSION_COOKIE_HTTPONLY、SESSION_COOKIE_SAMESITE见 channels/sessions.py。此外save_session()channels/sessions.py对 Django 5.1 使用异步的session.asave()更早版本则通过database_sync_to_async包装同步save()若存储抛出UpdateError例如用户已在并发请求中登出导致会话被删除会转换为SuspiciousOperation异常抛出。与 Django 会话设置的完整对齐SessionMiddleware使用到的 Django 设置均沿用标准 Django 语义设置项在中间件中的作用SESSION_COOKIE_NAME会话 Cookie 名默认sessionid读取与写回都依赖它SESSION_COOKIE_DOMAINCookie 的domain属性SESSION_COOKIE_PATHCookie 的path属性默认/SESSION_COOKIE_SECURE是否仅 HTTPS 发送SESSION_COOKIE_HTTPONLY是否设置HttpOnlySESSION_COOKIE_SAMESITESameSite策略strict/lax/noneSESSION_ENGINE会话存储后端决定SessionStore类如django.contrib.sessions.backends.dbSESSION_SAVE_EVERY_REQUEST为True时每次响应都保存会话注意要使用会话Django 的INSTALLED_APPS中需要包含django.contrib.sessions仓库测试在 tests/conftest.py 中如此配置并确保数据库迁移已执行默认 db 后端。测试验证仓库如何证明这些行为仓库测试直接印证了上述文档行为可作为你配置后的自检清单tests/test_http.pytest_sessions对SessionMiddlewareStack包裹的 HTTP 应用发起请求断言响应头中的Set-Cookie同时包含sessionid、expires、HttpOnly、Max-Age、Path且SameSiteLax——验证 HTTP 响应自动注入会话 Cookie。tests/test_http.pytest_session_saves写入fav_color后从后端SessionStore重新读取验证改动真实落库。tests/test_http.pytest_session_save_update_error故意 flush 会话后断言抛出SuspiciousOperation。tests/test_http.pytest_multiple_sessions多个并发连接各自持有独立 scope互不串扰。tests/test_generic_websocket.pytest_multiple_websocket_consumers_with_sessions用SessionMiddlewareStack包裹 WebSocket consumer乱序访问两个连接验证各连接使用自己的 scope——证明中间件同样适配 WebSocket 协议。进阶会话是认证的基础AuthMiddlewareStack会话在 Channels 中的另一个重要用途是为认证提供基础。在 channels/auth.py 中def AuthMiddlewareStack(inner): return CookieMiddleware(SessionMiddleware(AuthMiddleware(inner)))AuthMiddleware从scope[session]中读取用户标识与认证后端填充scope[user]如果 scope 中没有会话会抛出ValueError“SessionMiddleware must be above it”。因此凡是需要scope[user]的场景SessionMiddleware都是不可或缺的前置条件。更多细节可参考 docs/topics/authentication.rst。小结HTTP 与 WebSocket 都支持标准 Django 会话入口统一为scope[session]挂载顺序SessionMiddlewareStack CookieMiddleware(SessionMiddleware(...))作用于需要会话的所有 consumerHTTP 下响应状态码非 500会自动保存会话SESSION_SAVE_EVERY_REQUESTTrue可强制每次保存WebSocket 下会话只装载不自动保存务必调用scope[session].save()/await scope[session].asave()长轮询 HTTP consumer 请在发送响应前手动save()。赞分享后端WebSocket异步编程【免费下载链接】channelsDeveloper-friendly asynchrony for Django项目地址https://gitcode.com/gh_mirrors/ch/channels点击查看免费下载相关推荐web-flash完全指南基于Spring Boot和Vue.js的终极前后端分离解决方案web flash完全指南基于Spring Boot和Vue.js的终极前后端分离解决方案 web flash是一个基于Spring Boot和Vue.js的Django Channels中间件实战集成认证、会话和跨域支持Django Channels中间件实战集成认证、会话和跨域支持 Django Channels中间件是构建实时Web应用的关键组件它为WebSocket和后端WebSocket异步编程Badge Magic社区贡献指南如何参与开源LED应用开发Badge Magic社区贡献指南如何参与开源LED应用开发 Badge Magic是一款跨平台的开源LED应用开发工具支持iOS、Mac和Android系移动开发物联网上一篇CANN/GE ACL BLAS矩阵乘句柄创建API下一篇3大核心功能解放星穹铁道玩家双手March7thAssistant自动化工具全攻略创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考