You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 06:24:53