涉及技术栈:
后端: DjangoRestFrameWork前端: Vue.js + ElementUi
确保当前python环境下已经安装django与djangorestframe;python建议使用3.7版本的;稍微稳健一点;并且安装vue。安装完之后使用pycharm创建django目录;
创建完django目录后;进入项目根目录;打开dos命令行输入`vue ui`
服务启动完之后打开`http://localhost:8000/`创建Vue项目;比如我这边项目名输入`front`点击创建项目后耐心等待
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中间件注释掉
之后我们添加下数据库连接信息;确保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')),]
// 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
API测试平台h1> el-input> el-form-item> el-input> el-form-item> 登录el-button> el-form-item> el-form> el-col> el-row> div> div>template>