vue3项目学习三:配置登陆解决方案

news2025/2/25 11:36:10

配置登陆解决方案

  • 配置环境变量
  • 封装axios
    • 封装接口请求模块
    • 封装登录请求
    • 触发登录动作
    • 本地缓存处理方案
      • LocalStorage
    • 登录鉴权
    • 退出登录方案
      • 主动退出
      • 被动退出

配置环境变量

在根目录创建开发模式和生产模式的两种baseURL
在这里插入图片描述
输入:

ENV='development'

# base api
VUE_APP_BASE_API='/api'

修改vue.config.js代理

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'https://xxxxx/',
        changeOrigin: true
      }
    }
  }
}

封装axios

安装axios

npm i axios --save

创建封装文件:src -> utils -> request.js

import axios from 'axios'
import { ElMessage } from 'element-plus'
import store from '@/store'

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 5000
})

// 请求拦截器
service.interceptors.request.use(
  config => {
    // 注入token
    if (store.state.user.token) {
      // 如果存在token则注入token
      config.headers.Authorization = `Bearer ${store.state.user.token}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器
service.interceptors.response.use(
  // 请求成功
  response => {
    // 根据接口返回情况设置,此处为接口返回包括 success ,message , data
    const { success, message, data } = response.data
    // 判断当前请求是否成功? 返回解析后的数据 : 失败后消息提示
    if (success) {
      return data
    } else {
      // 失败,返回消息提示,使用element消息message模块
      ElMessage.error(message)
      return Promise.reject(new Error(message))
    }
  },
  // 请求失败 404 500 等
  error => {
    ElMessage.error(error.message)
    return Promise.reject(error)
  }
)

export default service


封装接口请求模块

创建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模块,用于处理所有与用户相关的内容。
在这里插入图片描述

store -> modules -> user.js

import { login } from '@/api/sys'

export default {
  namespaced: true,
  state: () => ({

  }),
  mutations: {

  },
  actions: {
    /**
     * 登录请求动作
     */
    login (context, userInfo) {
      const { username, password } = userInfo
      return new Promise((resolve, reject) => {
        login({ username, password }).then(data => {
          resolve(data)
        }).catch(err => {
          reject(err)
        })
      })
    }
  }
}

store -> index.js

import { createStore } from 'vuex'
import user from './modules/user'

export default createStore({
  modules: {
    user
  }
})

触发登录动作

login.vue

import { useStore } from 'vuex'

const store = useStore()
const handlelogin = () => {
	// 1.表单验证
	store.dispatch('user/login' , loginForm.value).then(()=>{
	// 2.登录后处理
	})
}

本地缓存处理方案

通常获取到token之后使用localStorageVuex
保存在 Localstorage 是为了方便实现 自动登录功能
保存在 vuex 中是为了后面在其他位置进行使用

LocalStorage

utils -> storage.js

/**
 * 存储数据
 */
export const setItem = (key, value) => {
  // value 分为两种情况:
  // 1.基数据类型
  // 2.复杂数据类型
  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 = () => {
  window.localStorage.clear()
}

使用案例:store-> modules -> user.js

import { login } from '@/api/sys'
import { setItem, getItem } from '@/utils/storage'

export default {
  namespaced: true,
  state: () => ({
    token: getItem('token') || ''
  }),
  mutations: {
    setToken (state, token) {
      state.token = token
      setItem('token', token)
    }
  },
  actions: {
    /**
     * 登录请求动作
     */
    login (context, userInfo) {
      const { username, password } = userInfo
      return new Promise((resolve, reject) => {
        login({ username, password }).then(data => {
          this.commit('user/setToken', data.token)
          resolve(data)
        }).catch(err => {
          reject(err)
        })
      })
    }
  }
}

登录鉴权

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

而想要实现这个功能,那么最好的方式就是通过 路由守卫 来进行实现
main.js平级创建permission.js文件

在这里插入图片描述
在main.js导入
在这里插入图片描述
permission.js

import router from '@/router'
import store from '@/store'

// 白名单,可以包括404,500等页面
const whiteList = ['/login']

/**
 * 路由前置守卫
 */
router.beforeEach((to, from, next) => {
  if (store.state.user.token) {
    // 1.用户已登录,不允许进入login
    if (to.path === '/login') {
      next('/')
    } else {
      next()
    }
  } else {
    // 2.用户未登录,只允许进入login
    if (whiteList.indexOf(to.path) > -1) {
      // 在白名单,直接通过
      next()
    } else {
      next('/login')
    }
  }
})

退出登录方案

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

那么无论是什么退出方式,在用户退出时,所需要执行的操作都是固定的:

  1. 清理掉当前用户缓存数据
  2. 清理掉权限相关配置
  3. 返回到登录页

主动退出

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

logout () {
  this.commit('user/setToken', '')
  this.commit('user/setUserInfo', {})
  removeAllItem()
  // TODO: 清理权限相关
  router.push('/')
}

退出时调用该方法即可

被动退出

用户被动退出的场景主要有两个:

  1. token 失效
  2. 单点登录:其他人登录该账号被“顶下来"

那么这两种场景下,在前端对应的处理方案一共也分为两种,共分为 主动处理、被动处理 两种:

  1. 主动处理:主要应对 token 失效
  2. 被动处理:同时应对 token 失效与单点登录

1.主动处理
此时用到的是“时效token”,对于 token 本身是拥有时效的,但是通常情况下这个时效都是在服务端进行处理。而此时我们要在服务端处理token时效的同时在前端主动介入token’时效的处理中。 从而保证用户信息的更加安全性。

对应到代码中的实现方案为

  1. 在用户登陆时,记录当前 登录时间
  2. 制定一个 失效时长
  3. 在接口调用时,根据 当前时间 对比 登录时间,看是否超过了 时效时长
    1. 如果未超过,则正常进行后续操作
    2. 如果超过,则进行 退出登录 操作

创建 utils/auth.js 文件,并写入以下代码

import { getItem, setItem } from './storage'

const TIME_STAMP = 'timeStamp'
const TOKEN_TIMEOUT_VALUE = 2 * 3600 * 1000

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

登录成功后设置时间戳,保存登录时间 -> 跳转页面 ,在每次请求接口时检查时间是否超时:
在这里插入图片描述
2. 被动处理
utils/request的响应拦截器中增加一下逻辑:

// 响应拦截器
service.interceptors.response.use(
  // 请求成功
  response => {
    // 根据接口返回情况设置,此处为接口返回包括 success ,message , data
    const { success, message, data } = response.data
    // 判断当前请求是否成功? 返回解析后的数据 : 失败后消息提示
    if (success) {
      return data
    } else {
      // 失败,返回消息提示,使用element消息message模块
      ElMessage.error(message)
      return Promise.reject(new Error(message))
    }
  },
  // 请求失败 404 500 等
  error => {
    if (error.response && error.response.data && error.response.data.code === 401) {
      store.dispatch('user/logout')
    }
    ElMessage.error(error.message)
    return Promise.reject(error)
  }
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1027634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

国内首款研发领域 AI 项目管理工具发布:PingCode AI

PingCode的使命,始终是用技术驱动研发生产力。 过去几年,PingCode在研发管理领域持续引领创新,基于“自动化、数据化、智能化”的战略三部曲,先后发布了研发【自动化】引擎、【效能度量】引擎,而对于最后一步“智能化”…

时序数据库 IoTDB 发布端边云原生解决方案,有效优化工业互联网数据上传时效与资源消耗...

2023 年 9 月 8 日,由中国通信学会、福建省工业和信息化厅主办的 2023 中国国际工业互联网创新发展大会在厦门举办。大会主论坛中,时序数据库 IoTDB 发表其自研建立的端边云原生解决方案,该方案可实现端侧设备、边缘服务器、数据中心数据的协…

400电话怎么办理(申请开通)

申请开通400电话是一项相对简单的过程,只需按照以下步骤进行操作即可。 第一步,选择400电话服务提供商。在市场上有很多公司提供400电话服务,您可以根据自己的需求和预算选择适合的服务商。可以通过搜索引擎、咨询朋友或者查看相关论坛等方式…

开学季ipad电容笔哪款好?便宜的电容笔推荐

随着数码产品不断地更新和添加新的特性功能,iPad的平板已经可以和笔记本电脑相媲美了。而时至今日,随着技术的进步,ipad已经不再是一款单纯的娱乐设备,而是一款集学习、绘画、办公于一体的功能。为提高生产力,搭配上一…

公共4G广播音柱有哪些用处

公共广播音柱有哪些用处 公共广播音柱是一种用于广播音频信号的设备,一般安装在公共场所或街道上。它具有以下几个主要用处: 1. 喊话广播:公共广播音柱可以用于喊话广播,用来传达重要信息、紧急通知、警报等,如公共安…

基于微信小程序的实验室预约管理系统设计与实现

前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻…

没有白走的路,这个结果你配得上。

作者 | 磊哥 来源 |公众号:Java中文社群 转载请联系授权(微信ID:GG_Stone) 几年前,我在看新三国时,有一段记忆深刻的话,司马懿获胜之后说:“我挥剑只有一次,却磨了十几年…

多线程的学习第二篇

多线程 线程是为了解决并发编程引入的机制. 线程相比于进程来说,更轻量 ~~ 更轻量的体现: 创建线程比创建进程,开销更小销毁线程比销毁进程,开销更小调度线程比调度进程,开销更小 进程是包含线程的. 同一个进程里的若干线程之间,共享着内存资源和文件描述符表 每个线程被独…

vue监听路由变化

//监听watch: {//监听路由$route (to, from) { //监听路由是否变化console.log(to.path);if(to.path "/Jindex/JuserindexAdd"){}}}, 升级 //监听watch: {//监听路由$route (to, from) { //监听路由是否变化let urlPath [/order/order,/order/listDate];console.l…

智能合约平台开发方案:构建可靠且高效的区块链应用

随着区块链技术的发展与应用,智能合约平台成为了构建去中心化应用的核心基础设施。本文将从技术架构、智能合约编写与测试、安全性和可扩展性等方面深入探讨智能合约平台的开发方案,旨在为开发者提供专业且有深度的思考,帮助他们构建可靠且高…

MongoDB 2023年度纽约 MongoDB 年度大会话题 -- MongoDB 数据模式与建模

开头还是介绍一下群,如果感兴趣PolarDB ,MongoDB ,MySQL ,PostgreSQL ,Redis, Oceanbase, 等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。加群请联系 liuaustin3 ,在新加的朋友会分到2群&…

【校招VIP】前端JS语言之CSS基础属性

考点介绍 CSS全称为Cascading Style Sheets,中文翻译为“层叠样式表”,简称CSS样式表,所以称之为层叠样式表(Cascading Stylesheet)简称CSS。在网页制作时采用CSS技术,可以有效地对页面的布局、字体、颜色、…

MyBatis 篇

目录 1、什么是MyBatis 2、说说MyBatis的优点和缺点 3、#{}和${}的区别是什么? 4、当实体类中的属性名和表中的字段名不一样 ,怎么办 ? 5、Mybatis是如何进行分页的?分页插件的原理是什么? 6、Mybatis是否支…

MLAgents (0) Unity 安装及运行

1、下载ML-Agents 下载地址 GitHub - Unity-Technologies/ml-agents: The Unity Machine Learning Agents Toolkit (ML-Agents) is an open-source project that enables games and simulations to serve as environments for training intelligent agents using deep reinfo…

【C++杂货铺】国庆中秋特辑——多态由浅入深详细总结

文章目录 一、多态的概念二、多态的定义及实现2.1 多态的构成条件2.2 虚函数2.3 虚函数的重写2.4 虚函数重写的两个例外2.4.1 协变(基类与派生类虚函数返回值类型不同)2.4.2 析构函数的重写(基类与派生类析构函数的名字不同) 2.5 …

【Java核心】JDK、JRE、 JVM的联系与区别

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ JDK、JRE、 JVM的联系与区别 1. 简述2. 是什么…

Linux查看系统信息

# 查看操作系统的详细信息 uname -a# 查看已安装的Linux发行版信息 cat /etc/os-release# 查看Linux Standard Base (LSB)的信息 lsb_release -a# 查看主机的信息 hostnamectl# 查看文件系统的磁盘空间使用情况 df -h# 查看系统内存的使用情况 free -h# 查看网络接口的信息 ifc…

【LeetCode75】第六十题 使用最小花费爬楼梯

目录 题目: 示例: 分析: 代码: 题目: 示例: 分析: 题目给我们一个数组,第i个数表示在第i个台阶起步所需的花费。我们可以从下标为0或是1的台阶出发,问我们最终到达顶…

【校招VIP】测试脚本语言之权限命令

考点介绍: 在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(command interpreter,命令解析器)。它类似于DOS下的http://COMMAND.COM和后来的cmd.exe…

nginx配置gzip压缩,优化传输效率,加快页面访问速度

文章目录 引言一、什么是nginx的gzip二、nginx的常用配置项三、使用示例四、浏览器查看gzip是否生效1. 判断浏览器是否支持gzip2. 判断gzip是否生效 总结 引言 在现代互联网的高速发展进程中,网站的访问速度愈发成为了用户选择和留存的关键。其中,通过g…