2025年【前端开发方案】后台管理系统之登录方案、退出登录方案记录

【前端开发方案】后台管理系统之登录方案、退出登录方案记录登录方案记录 需求 根据当前环境的不同 请求不同的 BaseUrl 解决 在根目录中新建 env development 与 env production 连个文件 进行配置 env production ENV production base api

大家好,我是讯享网,很高兴认识大家。

登录方案记录

需求:根据当前环境的不同,请求不同的 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': { // 要代理的服务器地址 这里不用写 api target: '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 } = userInfo return 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 = token setItem(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, ... })

退出登录方案记录 

 退出登录 它的触发时机一般有两种:

  • 用户主动退出:用户点击登录按钮之后退出
  • 用户被动退出:token 过期或被 其他人”顶下来“ 时退出

实现用户主动退出的对应策略

store/modules/user.js 中,添加对应 action

讯享网import router from '@/router' logout() { //一、清理掉当前用户缓存数据 this.commit('user/setToken', '') this.commit('user/setUserInfo', {}) removeAllItem() //二、清理掉权限相关配置 //三、返回到登录页 router.push('/login') }

为退出登录按钮添加点击事件,触发 logoutaction

import { useStore } from 'vuex' const store = useStore() const logout = () => { store.dispatch('user/logout') }

实现用户被动退出的对应策略之主动处理(应对 token 失效 )

constant 中声明对应常量

讯享网// token 时间戳 export const TIME_STAMP = 'timeStamp' // 超时时长(毫秒) 两小时 export const TOKEN_TIMEOUT_VALUE = 2 * 3600 * 1000

在用户登陆时,记录当前登录时间。创建 utils/auth.js 文件

import { TIME_STAMP, TOKEN_TIMEOUT_VALUE } from '@/constant' import { setItem, getItem } from '@/utils/storage' / * 获取时间戳 */ export function getTimeStamp() { return getItem(TIME_STAMP) } / * 设置时间戳 */ export function setTimeStamp() { setItem(TIME_STAMP, Date.now()) } / * 是否超时 */ export function isCheckTimeout() { // 当前时间戳 var currentTime = Date.now() // 缓存时间戳 var timeStamp = getTimeStamp() return currentTime - timeStamp > TOKEN_TIMEOUT_VALUE }

在用户登录成功之后去设置时间,到 store/user.jslogin 中:

讯享网import { setTimeStamp } from '@/utils/auth' login(context, userInfo) { ... return new Promise((resolve, reject) => { ... .then(data => { ... // 保存登录时间 setTimeStamp() resolve() }) }) }

utils/request 对应的请求拦截器中进行主动介入

import { isCheckTimeout } from '@/utils/auth' if (store.getters.token) { //判断是否过期 if (isCheckTimeout()) { // 登出操作 store.dispatch('user/logout') return Promise.reject(new Error('token 失效')) } ... }

实现用户被动退出的对应策略之被动处理(应对 token 失效 )

utils/request 的响应拦截器中,通过服务端返回的状态码进行判断:

讯享网// 响应拦截器 service.interceptors.response.use( response => { ... }, error => { // 处理 token 超时问题 if ( error.response && error.response.data && error.response.data.code === 401 ) { // token超时 store.dispatch('user/logout') } ElMessage.error(error.message) // 提示错误信息 return Promise.reject(error) } )

小讯
上一篇 2025-01-29 11:55
下一篇 2025-04-05 11:24

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/120802.html