Vue Element Admin 登陆认证
使用的是Vue Element Admin template 基础模板
1 修改 src/api/user.js
import request from '@/utils/request' export function login(data) { return request({ url: '/auth/', method: 'post', data }) } export function getInfo(token) { return request({ url: '/userInfo/', method: 'post', data:{'token':token} }) } export function logout() { return request({ url: '/logout/', method: 'post' }) }
2 修改src/store/modules/user.js
import { login, logout, getInfo } from '@/api/user' import { getToken, setToken, removeToken } from '@/utils/auth' import { resetRouter } from '@/router' const getDefaultState = () => { return { token: getToken(), name: '', avatar: '' } } const state = getDefaultState() const mutations = { RESET_STATE: (state) => { Object.assign(state, getDefaultState()) }, SET_TOKEN: (state, token) => { state.token = token }, SET_NAME: (state, name) => { state.name = name }, SET_AVATAR: (state, avatar) => { state.avatar = avatar } } const actions = { // user login login({ commit }, userInfo) { const { username, password } = userInfo return new Promise((resolve, reject) => { login({ username: username.trim(), password: password }).then(response => { const { data } = response.data commit('SET_TOKEN', data.token) setToken(data.token) resolve() }).catch(error => { reject(error) }) }) }, // get user info getInfo({ commit, state }) { return new Promise((resolve, reject) => { getInfo(state.token).then(response => { const { data } = response.data if (!data) { return reject('Verification failed, please Login again.') } const { name, avatar } = data commit('SET_NAME', name) commit('SET_AVATAR', avatar) resolve(data) }).catch(error => { reject(error) }) }) }, // user logout logout({ commit, state }) { return new Promise((resolve, reject) => { logout(state.token).then(() => { removeToken() // must remove token first resetRouter() commit('RESET_STATE') resolve() }).catch(error => { reject(error) }) }) }, // remove token resetToken({ commit }) { return new Promise(resolve => { removeToken() // must remove token first commit('RESET_STATE') resolve() }) } } export default { namespaced: true, state, mutations, actions }
3,修改src/utils/request.js
import axios from 'axios' import { MessageBox, Message } from 'element-ui' import store from '@/store' import { getToken } from '@/utils/auth' // create an axios instance const service = axios.create({ baseURL: process.env.VUE_APP_BASE_URL, // url = base url + request url // withCredentials: true, // send cookies when cross-domain requests timeout: 5000 // request timeout }) // request interceptor service.interceptors.request.use( config => { // do something before request is sent if (store.getters.token) { // let each request carry token // ['X-Token'] is a custom headers key // please modify it according to the actual situation //把Token信息加到请求头部 config.headers['X-Token'] = getToken() } return config }, error => { // do something with request error console.log(error) // for debug return Promise.reject(error) } ) export default service
4 配置后端接口
from django.http import JsonResponse from rest_framework.views import APIView from api import models from api.logger import logger def create_token(user): import hashlib import time #获取当前时间戳用作随机字符串 ctime = str(time.time()) m = hashlib.md5(bytes(user,encoding='utf-8')) m.update(bytes(ctime,encoding='utf-8')) return m.hexdigest() class AuthView(APIView): """ 用户登陆认证,生成并保存token """ authentication_classes = [] def post(self,request,*args,**kwargs): ret = {"code": 200, "status": "success", "data": {"token": None}} username = request.data.get('username') password = request.data.get('password') try: obj = models.Users.objects.filter(username=username,password=password).first() if obj: #为用户创建token,如果已存在则更新,否则创建 token = create_token(username) models.UserToken.objects.update_or_create(user=obj,defaults={'token':token}) ret['status'] = 'success' ret['data']['token'] = token else: ret['code'] = 401 ret['status'] = '用户名或密码错误' except Exception as e: logger.error(e) ret['code'] = 400 ret['status'] = 'error' return JsonResponse(ret) class AuthInfoView(APIView): """ 获取登陆用户信息 """ def post(self,request,*args,**kwargs): ret = {"code":200,"status":"success","data":{"roles":[],"introduction": '', "avatar": 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', "name": ''}} token = request.data.get('token') try: obj = models.UserToken.objects.filter(token=token).first() if obj: ret['status'] = 'success' ret['data']['name'] = obj.user.username for i in obj.user.roles.all(): ret['data']['roles'].append(i.title) else: ret['code'] = 401 ret['status'] = '认证失败' except Exception as e: logger.error(e) ret['code'] = 400 ret['status'] = 'error' return JsonResponse(ret) class LogoutView(APIView): """ 退出登陆 """ def post(self,request,*args,**kwargs): ret = {"code":200,"status":"success","data":'success'} token = request.META.get('HTTP_X_TOKEN') try: obj = models.UserToken.objects.filter(token=token).first() if obj: obj.delete() else: ret['code'] = 401 ret['status'] = '退出失败' except Exception as e: logger.error(e) ret['code'] = 400 ret['status'] = 'error' return JsonResponse(ret)
5 后端token认证
from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication from api import models class Authentication(BaseAuthentication): def authenticate(self, request): #获取请求头部的token token = request.META.get('HTTP_X_TOKEN') token_obj = models.UserToken.objects.filter(token=token).first() if not token_obj: raise exceptions.AuthenticationFailed('用户认证失败') return (token_obj.user,token_obj)
ps:携带token认证时出现了跨域问题(中间件配置)
from django.utils.deprecation import MiddlewareMixin class CORSMiddleware(MiddlewareMixin): def process_response(self, request, response): # 添加响应头 # 允许你的域名来获取我的数据 # 允许所有的域名来获取数据 response['Access-Control-Allow-Origin'] = '*' # 允许你携带Content-Type请求头 如果要多的用逗号,隔开 response['Access-Control-Allow-Headers'] = '*' return response
配置setting
MIDDLEWARE = [ 'api.cors.CORSMiddleware', #跨域请求CORS ]