「一旦把React部署到Netlify,Django留在PythonAnywhere,cookie就跨不过去了。」这是每个尝试前后端分离的开发者都会踩的坑。
session认证在同域时代没问题,但现代前端和后端天生分居两地。你需要一种不依赖cookie、不挑域名、服务器不用记状态的方案。JWT(JSON Web Tokens,一种基于令牌的认证机制)正是为此而生。
![]()
但认证只是入场券。真正麻烦的是:怎么确保用户A永远碰不到用户B的数据?哪怕他猜中了ID。
这篇教程拆解一个完整的个人笔记API实现——从自定义用户模型到数据隔离视图,每一步都带代码逻辑。
正方:JWT是前后端分离的最优解
支持方认为JWT解决了session认证的核心痛点:跨域失效。
session依赖cookie,而cookie有同源策略限制。前端在netlify.app,后端在pythonanywhere.com,浏览器直接拦截cookie携带。JWT把认证信息塞进HTTP头部的Authorization字段,彻底绕开cookie的域名枷锁。
更关键的是无状态。服务器不需要存储session表,收到请求时只验证令牌签名,立刻知道「你是谁」。这对水平扩展极其友好——新增服务器实例不用同步session数据。
SimpleJWT这个库把JWT集成进Django REST Framework的流程压缩到几行配置:安装、改settings.py、加两条URL路由,就能签发access token和refresh token。
反方:JWT不是银弹,数据隔离才是硬骨头
反对声音指出:很多人把JWT当成万能钥匙,却忽略了认证之后的授权问题。
知道「你是谁」和允许「你做什么」是两件事。教程中特意强调scoping(数据范围隔离)——这是比JWT配置更复杂的工程挑战。
危险场景很具体:假设笔记详情接口是/notes/42/,恶意用户登录后尝试/notes/43/、/notes/44/。如果后端不做隔离,他就可能遍历其他用户的数据。这叫ID枚举攻击。
Django的常规查询Note.objects.get(pk=pk)在这种攻击面前毫无防御。必须在查询层叠加用户过滤:Note.objects.filter(user=request.user)。
教程里的NoteViewSet用get_queryset()重写实现这层防护,但开发者很容易漏掉——毕竟JWT教程通常只讲到「拿到token就算成功」。
我的判断:JWT是基础设施,scoping是产品底线
两者不是竞争关系,是前后脚的关系。
JWT解决的是「能不能登录」的工程可行性问题。没有它,前后端分离架构在跨域场景下直接卡死。这是基础设施层。
Scoping解决的是「数据安不安全」的产品责任问题。一个笔记API如果能让用户A看到用户B的私密内容,功能再完整也是零分。这是安全底线。
教程的价值在于把两层问题串起来讲。Step 1到Step 5搭JWT管道,Step 6到Step 7砌数据隔离墙,Step 9用Postman演示攻击场景——完整闭环。
具体实现上,自定义UserModel是第一步。Django默认用户模型用username做主键,但现代应用通常用email。教程在2.1节定义email为唯一标识,2.2节用AUTH_USER_MODEL指向新模型,这是后续所有权限控制的地基。
Note模型的设计同样关键。外键必须指向settings.AUTH_USER_MODEL,而不是硬编码User。这样查询时才能链式过滤到当前登录者。
序列化器层也有讲究。UserSerializer要控制字段暴露——password只写不读,避免接口泄露哈希值。NoteSerializer则把user设为read_only,防止客户端伪造归属关系。
视图层的get_queryset()是最后一道闸门。教程7.1节的实现很标准:返回self.queryset.filter(user=self.request.user)。这行代码把Django ORM的表达能力转化成安全策略。
但有个细节容易被忽略:Django REST Framework的ViewSet默认支持list/retrieve/create/update/destroy五个动作。每个动作都走get_queryset()吗?
答案是肯定的。这是DRF的设计一致性——无论批量查还是单条查,统一入口过滤。但教程7.2节特别强调了retrieve场景的风险,因为单条接口的ID参数最容易被枚举。
测试环节的设计也很有教学价值。9.5节演示scoping的方式是:用用户A的token尝试操作用户B的笔记ID,预期收到404。这不是系统抛错,是查询结果为空——因为filter(user=A)把B的数据提前筛掉了。这种「静默失败」比403拒绝更安全,攻击者无法区分「ID不存在」和「存在但无权访问」。
Token过期处理是另一个实用话题。教程Step 10讲refresh token机制:access token短命(通常5-15分钟),refresh token长命(几天到几周)。用户无感知续签,但被盗的access token很快失效。SimpleJWT内置了/blacklist端点,可以把泄露的refresh token拉黑。
这套机制在移动端尤其重要。手机app不像浏览器能自动续cookie,需要显式管理token生命周期。
回头看整个技术选型:Django REST Framework提供视图层脚手架,SimpleJWT处理令牌逻辑,Django ORM做数据隔离。三者的接缝处——比如怎么把request.user传进查询集——是教程真正想教的东西。
比代码更重要的是设计意图。JWT让认证无状态,scoping让授权有边界。前后端分离不是把代码拆成两份,是把信任模型重新设计。
教程最后留了个开放尾巴:How You Can Improve This Project。可能的延伸包括分页(笔记多了不能一次性全拉)、搜索(全文检索需求)、版本控制(笔记历史记录)。这些都不是JWT或scoping能覆盖的,但架构已经搭好,增量功能有地方插。
数据收束:10个步骤,覆盖项目搭建、模型设计、认证配置、权限实现、接口测试完整链条。核心代码行数控制在200行以内,但涉及Django的6个关键配置文件和4层抽象(模型-序列化器-视图-路由)。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.