mock模拟接口测试 vue_Drf+Vue接口测试平台实现一切从登陆开始

环境准备

 涉及技术栈: 

后端: DjangoRestFrameWork前端: Vue.js + ElementUi
确保当前python环境下已经安装django与djangorestframe;python建议使用3.7版本的;稍微稳健一点;并且安装vue。安装完之后使用pycharm创建django目录;

mock模拟接口测试 vue_Drf+Vue接口测试平台实现一切从登陆开始_第1张图片

创建完django目录后;进入项目根目录;打开dos命令行输入`vue ui`

mock模拟接口测试 vue_Drf+Vue接口测试平台实现一切从登陆开始_第2张图片

服务启动完之后打开`http://localhost:8000/`创建Vue项目;比如我这边项目名输入`front`点击创建项目后耐心等待

后端登录功能实现

一切准备完之后;来带项目根目录输入`python manage.py startapp myauth` 创建一个用户应用; 然后再在项目下创建apps;并将刚才创建的myauth移动至apps目录下;最后的目录结构应该是这个样子的;

mock模拟接口测试 vue_Drf+Vue接口测试平台实现一切从登陆开始_第3张图片

完成以上步骤后;进入setting.py文件;首先我们先安装下pip install django-cors-headers;安装完后在INSTALLED_APPS中配置下刚才创建的应用和django-cors-headers、django-cors-headers是用来解决跨域问题的;
INSTALLED_APPS = [    'django.contrib.admin',    'django.contrib.auth',    'django.contrib.contenttypes',    'django.contrib.sessions',    'django.contrib.messages',    'django.contrib.staticfiles',    'corsheaders',    'apps.zlauth']    # 允许所有域名来访问我们的服务器CORS_ORIGIN_ALLOW_ALL = True
随后把csrf中间件注释掉

mock模拟接口测试 vue_Drf+Vue接口测试平台实现一切从登陆开始_第4张图片

之后我们添加下数据库连接信息;确保mysql数据库中已创建配置信息中的数据库
DATABASES = {    'default': {        'ENGINE': 'django.db.backends.mysql',        'NAME': 'interfaceplatform',        'USER': 'root',        'PASSWORD': '123456',        'HOST': '127.0.0.1',        'PORT': 3306    }}
最后配置下时区以及一些静态文件
# Internationalization# https://docs.djangoproject.com/en/3.0/topics/i18n/LANGUAGE_CODE = 'en-us'TIME_ZONE = 'Asia/Shanghai'USE_I18N = TrueUSE_L10N = TrueUSE_TZ = True# Static files (CSS, JavaScript, Images)# https://docs.djangoproject.com/en/3.0/howto/static-files/STATIC_URL = '/static/'STATICFILES_DIRS = [    os.path.join(BASE_DIR, "static")]MEDIA_ROOT = os.path.join(BASE_DIR, 'media')MEDIA_URL = '/media/'AUTH_USER_MODEL = "myauth.User"
User模型编写;进入models.py文件;填写下面代码后;在项目根目录输入python manage.py makemigrations; python manage.py migrate; 在mysql创建数据表成功后;输入python manage.py createsuperuser;创建一个用户;
from django.db import modelsfrom django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManagerfrom shortuuidfield import ShortUUIDFieldclass UserManager(BaseUserManager):    def _create_user(self, telephone, username, password, **kwargs):        if not telephone:            raise ValueError('请传入手机号码!')        if not username:            raise ValueError('请传入用户名!')        if not password:            raise ValueError('请传入密码!')        user = self.model(telephone=telephone, username=username, **kwargs)        user.set_password(password)        user.save()        return user    def create_user(self, telephone, username, password, **kwargs):        kwargs['is_superuser'] = False        return self._create_user(telephone, username, password, **kwargs)    def create_superuser(self, telephone, username, password, **kwargs):        kwargs['is_superuser'] = True        return self._create_user(telephone, username, password, **kwargs)class ZLUser(AbstractBaseUser, PermissionsMixin):    """    重写django自带的User表    """    uid = ShortUUIDField(primary_key=True, verbose_name="用户表主键")    telephone = models.CharField(unique=True, max_length=11, verbose_name="手机号码")    email = models.EmailField(unique=True, max_length=100, verbose_name='邮箱', null=True)    username = models.CharField(max_length=100, verbose_name="用户名", unique=False)    avatar = models.CharField(max_length=200, verbose_name='头像链接')    date_joined = models.DateTimeField(auto_now_add=True, verbose_name='加入时间')    is_active = models.BooleanField(default=True, verbose_name="是否可用")    USERNAME_FIELD = 'telephone'    REQUIRED_FIELDS = ['username']    EMAIL_FIELD = 'email'    objects = UserManager()    def get_full_name(self):        return self.username    def get_short_name(self):        return self.username
重写Jwt用户认证;在用户模块下创建authorizations.py文件;
import jwtfrom datetime import datetime, timedeltafrom django.conf import settingsfrom django.http import JsonResponsefrom rest_framework.authentication import BaseAuthentication, get_authorization_headerfrom rest_framework import exceptionsfrom django.contrib.auth import get_user_modelfrom jwt.exceptions import ExpiredSignatureErrorMTUser = get_user_model()def generate_jwt(user):    expire_time = datetime.now() + timedelta(days=7)    return jwt.encode({"userid": user.pk, "exp": expire_time}, key=settings.SECRET_KEY).decode('utf-8')class JWTAuthentication(BaseAuthentication):    keyword = 'JWT'    def authenticate(self, request):        auth = get_authorization_header(request).split()        if not auth or auth[0].lower() != self.keyword.lower().encode():            return None        if len(auth) == 1:            msg = "不可用的JWT请求头!"            raise exceptions.AuthenticationFailed(msg)        elif len(auth) > 2:            msg = '不可用的JWT请求头!JWT Token中间不应该有空格!'            raise exceptions.AuthenticationFailed(msg)        try:            jwt_token = auth[1]            jwt_info = jwt.decode(jwt_token, settings.SECRET_KEY)            userid = jwt_info.get('userid')            try:                # 绑定当前user到request对象上                user = MTUser.objects.get(pk=userid)                return user, jwt_token            except:                msg = '用户不存在!'                raise exceptions.AuthenticationFailed(msg)        except ExpiredSignatureError:            msg = "JWT Token已过期!"            raise exceptions.AuthenticationFailed(msg)
创建用户的序列化模型; 在用户模块下创建serializers.py
from rest_framework import serializersfrom django.contrib.auth import get_user_modelZLUser = get_user_model()class UserSerializer(serializers.ModelSerializer):    class Meta:        model = ZLUser        fields = ['uid', 'telephone', 'username', 'email', 'avatar', 'date_joined', 'is_active']
编写登录接口
from rest_framework import viewsfrom rest_framework.authtoken.serializers import AuthTokenSerializerfrom rest_framework.response import Responsefrom django.contrib.auth import get_user_modelfrom django.utils.timezone import nowfrom .authorizations import generate_jwtfrom .serializers import UserSerializerfrom apps.zlauth.authorizations import JWTAuthenticationfrom rest_framework.permissions import IsAuthenticatedimport shortuuidimport osfrom django.conf import settingsUser = get_user_model()class LoginView(views.APIView):    def post(self, request):        serializer = AuthTokenSerializer(data=request.data, context={"request": request})        if serializer.is_valid():            user = serializer.validated_data.get('user')            user.last_login = now()            user.save()            token = generate_jwt(user)            user_serializer = UserSerializer(user)            return Response(data={"token": token, "user": user_serializer.data})        else:            print(serializer.errors)            return Response(data={"message": "数据提交错误!"})
添加路由映射;在用户模块下创建urls.py文件
from django.urls import pathfrom . import viewsapp_name = 'zlauth'urlpatterns = [    path('login', views.LoginView.as_view(), name='login'),]
并在项目总urls.py文件中用include路由分发将用户的相关子路由;关联到项目总的urls
from django.contrib import adminfrom django.urls import path, includeurlpatterns = [    path('auth/', include('apps.zlauth.urls')),]

前端登录功能实现

在前端src目录下创建uitls文件夹;并添加http与auth等js文件
// authconst USER_KEY = "USER_KEY"const TOKEN_KEY = "JWT_TOKEN_KEY"class Auth {  constructor() {    this.token = null    this.user = null    this.token = localStorage.getItem(TOKEN_KEY)    const userJson = localStorage.getItem(USER_KEY)    if (userJson && userJson != 'undefined') {      this.user = JSON.parse(userJson)    }  }  static getInstance() {    if (!this._instance) {      this._instance = new Auth()    }    return this._instance  }  setUserToken(user, token) {    this.user = user    this.token = token    localStorage.setItem(USER_KEY, JSON.stringify(user))    localStorage.setItem(TOKEN_KEY, token)  }  setUser(user) {    this.user = user    localStorage.setItem(USER_KEY, JSON.stringify(user))  }  clearUserToken() {    this.user = null;    this.token = null;    localStorage.removeItem(USER_KEY)    localStorage.removeItem(TOKEN_KEY)  }  get is_authed() {    if (this.user && this.token) {      return true    } else {      return false    }  }}export default Auth.getInstance()
// httpimport axios from "axios"import auth from "./auth"const BASE_URL = "http://127.0.0.1:8000"// const BASE_URL = "http://118.24.0.251:8000"class Http {  constructor() {    this.http = axios.create({      baseURL: BASE_URL    })    // 设置拦截器,用来添加JWT Token的    this.http.interceptors.request.use(config => {      const token = auth.token;      if (token && token != 'undefined') {        config.headers.common.Authorization = "JWT " + token      }      return config    })    // 设置拦截器,如果返回403,跳转到登陆页面    // 403是没有权限访问这个接口    this.http.interceptors.response.use(null, err => {      if (err && err.response && err.response.status == 403) {        auth.clearUserToken()      }      return Promise.reject(err);    })  }  login(params) {    const url = "/auth/login"    return this.http.post(url, params)  }}export default new Http()
最后 components 组建中新增Login.vue