Axios请求Djoser用户注册路由报401错误,但Postman可正常请求
Django + Vue.js 用户注册接口401/400错误排查与解决
问题背景
我是Django新手,正在用REST API结合Vue.js前端实现基础用户认证功能,使用Axios发送注册请求时遇到权限错误,Postman测试接口正常,但前端请求始终失败。
相关配置代码
Axios全局配置(axios.js)
import axios from 'axios' axios.defaults.withCredentials = true axios.defaults.baseURL = 'http://localhost:8000'
Vue注册组件逻辑(register.vue)
const submitRegistration = () => { axios.post('api/v1/users/', {username: 'userName', password: 'userPassword'}) .then(res => { console.log(res) }) }
Django路由配置(projectName/urls.py)
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/', include('djoser.urls')), path('api/v1/', include('djoser.urls.authtoken')), ]
Django全局配置(settings.py)
INSTALLED_APPS = [ ..., 'corsheaders', 'rest_framework', 'rest_framework.authtoken', 'djoser' ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', ..., ] CORS_ALLOWED_ORIGINS = ['http://localhost:3000'] CORS_ALLOW_CREDENTIALS = True REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAuthenticated', ) }
Vue全局请求头设置(app.vue)
onMounted(() => { if (store.authToken) { axios.defaults.headers.common['Authorization'] = `Token ${store.authToken}` } })
Vue状态管理初始化代码
import {reactive} from "vue"; export const store = reactive({ authToken: localStorage.authToken ?? null, })
错误现象
- 前端发送注册请求时,抛出401 Unauthorized错误
- 移除app.vue中设置请求头的代码后,错误变为400 BAD_REQUEST
- Postman直接调用
http://localhost:8000/api/v1/users/可正常创建用户
问题原因
- 全局权限配置冲突:settings.py中把
DEFAULT_PERMISSION_CLASSES设为IsAuthenticated,导致所有接口默认要求已认证用户才能访问,但Djoser的注册接口/api/v1/users/属于公开接口,应该允许匿名访问。 - 请求头异常:虽然注册时store.authToken理论上为null,但可能存在localStorage残留值,或者Axios全局头被意外篡改,导致请求携带无效Token触发401;移除请求头设置后,又因为全局权限要求认证,返回400错误。
解决方案
方案1:调整Django全局权限配置
将默认权限改为允许匿名访问,后续在需要认证的自定义视图中单独设置权限:
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', ), 'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.AllowAny', # 默认允许匿名访问 ) }
方案2:单独配置Djoser注册接口权限
如果不想修改全局权限,可以通过自定义Djoser视图或路由装饰器,给注册接口单独设置AllowAny权限:
# 示例:自定义Djoser用户视图并设置权限 from djoser.views import UserViewSet from rest_framework.permissions import AllowAny class CustomUserViewSet(UserViewSet): def get_permissions(self): if self.action == 'create': return [AllowAny()] return super().get_permissions() # 在urls.py中替换原Djoser路由 path('api/v1/users/', CustomUserViewSet.as_view({'post': 'create'})),
方案3:确保注册请求的请求头干净
在注册请求时显式清除Authorization头,避免携带无效值:
const submitRegistration = () => { axios.post('api/v1/users/', {username: 'userName', password: 'userPassword'}, { headers: { 'Authorization': undefined // 清除当前请求的认证头 } }) .then(res => { console.log(res) }) }
同时检查localStorage中是否有残留的authToken值,确保注册时store.authToken为null。
内容的提问来源于stack exchange,提问作者Artur Müller Romanov
相关产品推荐
相关产品推荐

