Vue.js前端向Django Rest Framework视图传递认证令牌问题
问题描述
我正在使用Django Rest Framework作为后端、Vue.js作为前端开发Web应用,已通过DRF的TokenAuthentication配置了基于令牌的认证,但目前在从Vue.js向需要登录用户的DRF视图传递认证令牌时遇到问题。
Django 配置代码
class CreateUserView(generics.CreateAPIView): """Create a new user in the system""" serializer_class = UserSerializer class CreateTokenView(ObtainAuthToken): """Create a new auth token for user""" serializer_class = AuthTokenSerializer renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES class ManageUserView(generics.RetrieveUpdateAPIView): """Manage the authenticated user""" serializer_class = UserSerializer authentication_classes = (authentication.TokenAuthentication, ) permission_classes = (permissions.IsAuthenticated, ) def get_object(self): """Retrieve and return authenticated user""" return self.request.user # view for board class CreateBoardView(generics.CreateAPIView): # Create Board queryset = Board.objects.all() serializer_class = BoardSerializer permission_classes = [permissions.IsAuthenticated] def perform_create(self, serializer): # create board board = serializer.save() # create BoardUser with owner set to True user = self.request.user board_user = BoardUser.objects.create( board=board, user=user, is_owner=True ) data = { 'board': BoardSerializer(board).data, 'board_user': BoardUserSerializer(board_user).data } return Response(data, status=status.HTTP_201_CREATED)
Vue.js 配置代码
<template> <div> <h2>注册</h2> <form @submit.prevent="register"> <label for="email">邮箱:</label> <input type="email" id="email" v-model="registerForm.email" required> <label for="first_name">名字:</label> <input type="text" id="first_name" v-model="registerForm.first_name" required> <label for="last_name">姓氏:</label> <input type="text" id="last_name" v-model="registerForm.last_name" required> <label for="password">密码:</label> <input type="password" id="password" v-model="registerForm.password" required> <button type="submit">注册</button> </form> <h2>登录</h2> <form @submit.prevent="login"> <label for="loginEmail">邮箱:</label> <input type="email" id="loginEmail" v-model="loginForm.email" required> <label for="loginPassword">密码:</label> <input type="password" id="loginPassword" v-model="loginForm.password" required> <button type="submit">登录</button> </form> <h2>创建新看板</h2> <form @submit.prevent="createBoard"> <label for="boardName">看板名称:</label> <input type="text" id="boardName" v-model="boardcreateForm.boardName" required> <label for="boardDescription">描述:</label> <textarea id="boardDescription" v-model="boardcreateForm.description"></textarea> <label for="dueDate">截止日期:</label> <input type="date" id="dueDate" v-model="boardcreateForm.due_date" required> <button type="submit">创建</button> </form> </div> </template> <script> import axios from 'axios'; export default { data() { return { registerForm: { email: '', first_name: '', last_name: '', password: '' }, loginForm: { email: '', password: '' }, boardcreateForm: { boardName: '', description: '', due_date: '' } }; }, methods: { async register() { try { const response = await axios.post('http://127.0.0.1:8000/user/create/', this.registerForm); console.log(response.data); // 可选:处理注册成功的响应 } catch (error) { console.error('注册错误:', error.response.data); } }, async login() { try { const response = await axios.post('http://127.0.0.1:8000/user/token/', this.loginForm); const token = response.data.token; localStorage.setItem('token', token); // 将令牌保存到localStorage console.log('登录成功'); } catch (error) { console.error('登录错误:', error.response.data); } }, async createBoard() { try { const token = localStorage.getItem('token'); if (!token) { console.error('未找到认证令牌,请先登录'); return; } const response = await axios.post('http://127.0.0.1:8000/board/create_board/', { name: this.boardcreateForm.boardName, description: this.boardcreateForm.description, due_date: this.boardcreateForm.due_date }, { headers: { Authorization: `Token ${token}`, "Content-Type": "application/json", } }); console.log(response.data); // 可选:处理看板创建成功的响应 } catch (error) { console.error('看板创建错误:', error.response ? error.response.data : error.message); } } } }; </script>
问题修复点
1. Django 视图认证配置缺失
CreateBoardView仅设置了权限控制,但未指定认证方式,DRF无法解析令牌。需添加认证类配置:
authentication_classes = (authentication.TokenAuthentication, )
修改后的CreateBoardView核心代码:
class CreateBoardView(generics.CreateAPIView): queryset = Board.objects.all() serializer_class = BoardSerializer authentication_classes = (authentication.TokenAuthentication, ) permission_classes = [permissions.IsAuthenticated] # 原perform_create方法代码保持不变
2. Vue.js 认证头格式错误
DRF的Token认证要求Authorization头格式为Token <令牌内容>,原代码多了冒号,需修正为:
Authorization: `Token ${localStorage.getItem('token')}`
3. Vue 数据绑定不一致
模板中看板名称绑定的是boardcreateForm.boardName,但data里定义的是boardcreateForm.name,导致提交时name字段为空,需将data中的name改为boardName,保持与模板一致。
4. 可选优化:添加令牌存在性检查
在createBoard方法中先判断令牌是否存在,避免未登录状态下的无效请求。
内容的提问来源于stack exchange,提问作者mkownak
相关产品推荐
相关产品推荐

