> 文章列表 > 后台管理系统之登录方案记录

后台管理系统之登录方案记录

后台管理系统之登录方案记录

需求:根据当前环境的不同,请求不同的 BaseUrl

解决:在根目录中新建.env.development与.env.production连个文件,进行配置:

# .env.production
ENV = 'production'# base api
VUE_APP_BASE_API = '/prod-api'# .env.development
ENV = 'development'# base api
VUE_APP_BASE_API = '/api'

然后在utils/request.js中配置:

import axios from 'axios'const service = axios.create({//process.env 表示当前环境下的所有环境变量baseURL: process.env.VUE_APP_BASE_API, timeout: 5000
})export default service

问题: 

出现这个问题的原因,是因为我们在前面配置环境变量时指定了 开发环境下,请求的 BaseUrl/api;这样的一个请求会被自动键入到当前前端所在的服务中,所以我们最终就得到了 http://192.168.18.42:8081/api/sys/login 这样的一个请求路径

解决:通过指定 webpack DevServer 代理 的形式,代理当前的 url 请求;在vue.config.js中进行如下编辑

module.exports = {devServer: {// 配置反向代理proxy: {// 当地址中有/api的时候会触发代理机制'/api': {// 要代理的服务器地址  这里不用写 apitarget: 'https://api.xxxxxxx.club/',changeOrigin: true // 是否跨域}}},xxxxxxxxx
}

在vuex中进行请求处理

创建 api 文件夹,创建 sys.js ,配置请求:

import request from '@/utils/request'/*** 登录*/
export const login = data => {return request({url: '/sys/login',method: 'POST',data})
}

将封装登录请求处理封装到 vuexaction 中。在 store 下创建 modules 文件夹,创建 user.js 模块,进行请求处理:

import { login } from '@/api/sys'
import md5 from 'md5'
export default {namespaced: true,state: () => ({}),mutations: {},actions: {login(context, userInfo) {const { username, password } = userInforeturn new Promise((resolve, reject) => {login({username,// md5用来将密码加密处理password: md5(password)}).then(data => {resolve()}).catch(err => {reject(err)})})}}
}

store/index 中完成注册:

import { createStore } from 'vuex'
import user from './modules/user.js'
export default createStore({modules: {user}
})

login 中,触发定义的 action

<template>xxxxxx</template>
<script setup>
import { useStore } from "vuex";const store = useStore();
const handleLogin = () => {//先校验数据,校验省略,数据格式校验通过进行登录store.dispatch("user/login", loginForm.value).then(() => {// TODO: 登录后操作}).catch((err) => {console.log(err);});
};
</script>

本地缓存处理方案

创建 utils/storage.js 文件,封装对本地LocalStorage的操作:注意两种不同数据类型的处理

/*** 存储数据*/
export const setItem = (key, value) => {// 将数组、对象类型的数据转化为 JSON 字符串进行存储if (typeof value === 'object') {value = JSON.stringify(value)}window.localStorage.setItem(key, value)
}/*** 获取数据*/
export const getItem = key => {const data = window.localStorage.getItem(key)try {return JSON.parse(data)} catch (err) {return data}
}/*** 删除数据*/
export const removeItem = key => {window.localStorage.removeItem(key)
}/*** 删除所有数据*/
export const removeAllItem = key => {window.localStorage.clear()
}

创建 constant 常量目录 constant/index.js

export const TOKEN = 'token'

vuexuser 模块下,处理 token 的保存:

import { login } from '@/api/sys'
import md5 from 'md5'
import { setItem, getItem } from '@/utils/storage'
import { TOKEN } from '@/constant'
export default {namespaced: true,state: () => ({token: getItem(TOKEN) || ''}),mutations: {setToken(state, token) {state.token = tokensetItem(TOKEN, token)}},actions: {login(context, userInfo) {....then(data => {this.commit('user/setToken', data.data.data.token)resolve()})...})}}
}

通过axios响应拦截器处理data.data.data.token问题。在 utils/request.js 中编码:

先放上响应的数据结果:

import axios from 'axios'
import { ElMessage } from 'element-plus'...
// 响应拦截器
service.interceptors.response.use(response => {const { success, message, data } = response.data//   要根据success的成功与否决定下面的操作if (success) {return data} else {// 业务错误ElMessage.error(message) // 提示错误消息return Promise.reject(new Error(message))}},error => {// TODO: 将来处理 token 超时问题ElMessage.error(error.message) // 提示错误信息return Promise.reject(error)}
)export default service

再修改下vuex 中的 user 模块 :

this.commit('user/setToken', data.token)

登录鉴权

当用户未登陆时,不允许进入除 login 之外的其他页面。用户登录后,token 未过期之前,不允许进入 login 页面

根目录创建permission.js,并在main.js中导入:

import router from './router'
import store from './store'// 白名单
const whiteList = ['/login']
/*** 路由前置守卫*/
router.beforeEach(async (to, from, next) => {// 存在 token ,进入主页// if (store.state.user.token) {// 快捷访问if (store.getters.token) {if (to.path === '/login') {next('/')} else {next()}} else {// 没有token的情况下,可以进入白名单if (whiteList.indexOf(to.path) > -1) {next()} else {next('/login')}}
})

在此处的 getters 被当作 快捷访问 的形式进行访问,所以我们需要声明对应的模块,创建 store/getters

const getters = {token: state => state.user.token
}
export default getters

store/index 中进行导入:

import getters from './getters'
export default createStore({getters,...
})