Django REST+React中CSRFToken与Knox认证的密码修改问题排查
解决Django REST + Knox Token认证下密码修改接口的CSRF与重定向问题
看起来你遇到的核心矛盾是:Django自带的password_change视图是为传统session认证的Web应用设计的,而你的项目采用的是Knox Token的无状态REST认证体系,两者不兼容导致了一系列问题。下面逐个解决你的三个问题:
核心解决方案:替换为DRF风格的密码修改API视图
首先要抛弃Django Auth自带的password_change视图,改用DRF实现自定义的密码修改接口,适配Knox Token认证。
1. 在views.py中添加自定义密码修改视图
from django.contrib.auth import update_session_auth_hash from rest_framework import status, generics from rest_framework.permissions import IsAuthenticated from knox.auth import TokenAuthentication class PasswordChangeAPI(generics.UpdateAPIView): authentication_classes = (TokenAuthentication,) permission_classes = (IsAuthenticated,) def update(self, request, *args, **kwargs): user = request.user old_password = request.data.get('old_password') new_password1 = request.data.get('new_password1') new_password2 = request.data.get('new_password2') # 验证旧密码正确性 if not user.check_password(old_password): return Response({"old_password": ["旧密码输入错误"]}, status=status.HTTP_400_BAD_REQUEST) # 验证新密码一致性 if new_password1 != new_password2: return Response({"new_password2": ["两次输入的新密码不一致"]}, status=status.HTTP_400_BAD_REQUEST) # 更新密码 user.set_password(new_password1) user.save() # 注意:Knox Token认证不需要更新session,这行是给session认证用的,可注释 # update_session_auth_hash(request, user) return Response({"detail": "密码修改成功"}, status=status.HTTP_200_OK)
2. 更新urls.py,替换默认的auth路由
把原来的path('', include('django.contrib.auth.urls')),替换为自定义接口的路由:
urlpatterns = [ # ... 其他原有路由保持不变 path('password-change/', PasswordChangeAPI.as_view(), name='password_change'), # 删除或注释掉原来的include('django.contrib.auth.urls') ]
逐个解决你的具体问题
问题1:可浏览API调用password_change重定向到登录页
现在使用DRF的自定义视图后,可浏览API会支持Knox Token认证:
- 打开可浏览API页面,点击右上角的Authorize按钮
- 输入格式为
Token <你的Knox Token值>的内容,完成认证 - 再调用
/accounts/password-change/接口,就会正常返回JSON响应,不会重定向到登录页
问题2:Postman调用接口因CSRF报错
DRF对非session类的认证(比如Knox Token)会自动跳过CSRF验证,现在你只需要:
- 在Postman的请求Headers中添加
Authorization: Token <你的Knox Token> - 请求Body中传入
old_password、new_password1、new_password2的JSON数据 - 直接发送POST请求即可,不会再出现CSRF相关报错
问题3:React前端的CSRF与重定向问题
解决重定向问题
自定义视图返回的是JSON响应,不再是Django自带的重定向,所以前端提交后不会跳转到其他页面,你可以在then回调里处理成功逻辑(比如提示用户密码修改成功)。
解决CSRF Token获取问题
因为我们用的是Token认证,不需要CSRF保护(CSRF是针对session认证的攻击场景设计的,Token认证是无状态的,每个请求都携带Token,天然避免CSRF风险),所以你可以:
- 去掉前端Axios中关于CSRF的配置(
xsrfCookieName、xsrfHeaderName这些) - 不需要再通过
react-cookie获取csrftoken
修正前端代码的小bug
你的ChangePassword.js中输入框的value绑定错误,会导致输入内容无法正确更新,修正如下:
// 修正输入框的value绑定 <input type="password" name="old_password" value={this.state.credentials.old_password} onChange={this.inputChanged} onKeyPress={this.pressedEnter}/><br/> <input type="password" name="new_password1" value={this.state.credentials.new_password1} onChange={this.inputChanged} onKeyPress={this.pressedEnter}/><br/> <input type="password" name="new_password2" value={this.state.credentials.new_password2} onChange={this.inputChanged} onKeyPress={this.pressedEnter}/><br/>
同时修正Axios的baseURL,指向你的Django API地址:
// 在Index.js中修改 axios.defaults.baseURL = 'http://127.0.0.1:8000/accounts/';
内容的提问来源于stack exchange,提问作者Onursezn
相关产品推荐
相关产品推荐

