5.单点登录(Vue2.x)

news2025/1/17 1:15:57

概况

百度百科

单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

关键词

tokensessioncookie统一的认证系统

流程说明

这里将 一期 系统比喻主系统,二期 系统使用(跳转到) 一期 系统的登录认证。

  1. 打开二期主页,当没有登录权限token,跳转到一期登录页。并在跳转的 url 中带上二期 url,用于登录成功后跳回二期。
    在这里插入图片描述

    2.在 一期 登录成功后,url 中带上参数 token 并返回到 二期 系统;

在这里插入图片描述

  1. 在新窗口中打开 一期 主页,默认已登录。点击 “注销” (此时向后台接口发请求注销 token,并 删除相关Cookie信息),返回登录页;
  2. 当在新窗口中打开二期页或刷新页面,调相关接口token验证接口。如果接口返回http 401,则token已失效。此时会返回一期登录页,重新登录(即图一)。

在这里插入图片描述

代码实现

注意要安装插件 js-cookie

npm i js-cookie

公共方法,一期和二期都有使用。解析

function getParamFromUrl() {
  let url = location.href;
  let map = {}
  let paramsStr = url.split('?')[1]
  if (paramsStr) {
      let paramStrList = paramsStr.split('&')
      for (let i = 0; i < paramStrList.length; i++) {
          let param = paramStrList[i].split('=')
          map[param[0]] = param[1]
      }
  }
  return map;
}

cookie Id,注意一期和二期同名。

const tokenCookieId = 'user_token';

二期

config.js

// 一期API服务地址
const ApiUrl  = 'http://192.168.182.243:8088/';
// 一期登录页面
const LoginUrl = "http://192.168.182.243:8088/login"

main.js

先判断是否有token

import Cookie from 'js-cookie'

// 解析 url 参数
let token = getParamFromUrl().token;

// url 是否带有 token
if (token) {
      Cookie.set(tokenCookieId, params.token);
      init(token);
} else {// Cookie 中能否找到 token
      token = Cookie.get(tokenCookieId);
      init(token);
}

初始化方法,判断是否有 token

  1. 没有 token,则直接跳转登录;
  2. token,验证 token 是否有效,无效则直接跳转登录。**有效*则进入系统;
import axios from 'axios'

function init(token) {
  if (token) {    
    let newAxios = axios.create({
      baseURL: ApiUrl,
      headers: { 'Authorization': token.replace('%20', ' ') }
    })
    // 获取用户信息,同时验证 token 是否有效
    newAxios.get(`/api/user/myinfo`).then((response) => {
      store.commit('user/SET_NAME', {
        userName: response.data.username,
        isManager: response.data.manager
      })
      // 注意:此时在初始化 Vue 主页
      return new Vue({
        el: '#app',
        router,
        store,
        render: h => h(App)
      })
    })
    .catch((error) => {
        // 一般会返回 401,token失效。移除 Cookie 中的 token,
        Cookie.remove(tokenCookieId);
        // 跳转到一期去登录,注意带上本页的 url,用于跳回
        location.href = LoginUrl + "?redirect=" + location.origin;
    })
  } else {// 根本就没有 token,一般为首次打开系统页面
      Cookie.remove(tokenCookieId);
      location.href = LoginUrl + "?redirect=" + location.origin;
  }
}

一期

router/index.js

路由前置守卫(全局) router.beforeEach

router.beforeEach((to, from, next) => {
  	let redirUrl = getParamFromUrl().redirect;
  	// Vuex store 也是从 Cookie 中获取,这里是项目截取,也可直接使用 Cookie.get
  	store.commit('user/REFRESH_NAME');
  	// 判断是否有 token  
  	if (store.state.user.token) {
      	// 是否有重定向 url,有则说明是从二期系统发来的请求。带上token返回到一期系统
    	if(redirUrl) {
      		location.href = redirUrl+'?token='+store.state.user.token
    	}
    	else if (to.path == '/login') {
      		next('/first')
    	}
        else {
              let pages = ''
              if(store.state.user.pages){
                pages = store.state.user.pages.split(',')
              }  
              if (store.state.user.isManager) {
                next()
              }
              else if (authorPages.indexOf(to.path) == -1) {
                	next()
              }
              else if (pages.indexOf(to.path ) > -1) {
                	next()
              } 
              else {
                	next('/noAuthor')
              }
        }
      } else {
            if(redirUrl) {// 没token 且从二期发来的请求,直接进入登录页即可
              	next()
            }
            else if (authorPages.indexOf(to.path) == -1){
              	next()
            }
            else if(to.path == '/login') {
              	next()
            }
            else {
              	next('/login')
            }
      }
})

App.vue

mounted 方法

mounted () {
    // 二期url
    let redirectUrl = getParamFromUrl().redirect;
    let token = Cookie.get(tokenCookieId);
    if (redirectUrl && token) {// 有 redirect 和 token 就返回到二期
      	location.href = decodeURIComponent(redirectUrl) + "?token=" + token;
    }
    else{// 一期,说明直接从一期打开。如下操作为可选项,如获取用户信息
      	let url = `/api/user/myinfo`;
      	this.$axios.get(url).then((response) => {
        	this.$store.commit('user/SET_NAME', {
          		userName: response.data.username,
          		isManager: response.data.manager
        	})
      	})
      	.catch((error) => {
        	this.$store.dispatch('user/logout');
        	if (!redirectUrl) {// 不是从二期进入,则直接去登录
          		this.$router.push('/login')
        	}
      	})
    }
}

store/modules/user.js

logout登出方法,删除相关 Cookie

const actions = {
  logout ({ commit }) {
    Cookies.remove('user_name')
    Cookies.remove('user_token')
    Cookies.remove('user_isManager')
    mutations.REFRESH_NAME(state)
  }
}

views/login.vue

登录时,如果有 redirect,则是从二期跳转过来的。

commit () {
  	if (this.inputName.trim() == '' || this.inputPw.trim() == '') {
    	this.$message({ type: 'error', message: '请输入用户名密码!' });
    	return;
  	}
  	let form = {
    	userName: this.inputName,
    	password: md5(this.inputPw),
  	}
  	// 登录请求
  	let navUrl = 'api/user/login'
  	this.$axios.post(navUrl, form).then((resp) => {
      	if (resp.data.success) {
        	let token = resp.data.token;
        	this.$store.commit('user/SET_TOKEN', token);
        	// 是否为二期请求
        	let redirectUrl = getParamFromUrl().redirect;
        	if (redirectUrl) {// 是二期请求,带着 token 跳转回去
          		location.href = decodeURIComponent(redirectUrl) + "?token=" + token;
        	} else {// 不是,则进入一期系统
          		location.reload()
        	}
      	} else {
        	this.$message({ type: 'error', message: resp.data.message })
      	}
    })
    .catch((error) => {
      	this.$message({ type: 'error', message: error })
    })
},

TopHeader.vue 和 Adminbox.vue

注销时一定要调后台接口,真正是注销服务端的 token。

// 清除用户相关信息
this.$store.dispatch("user/logout");
// 跳转到登录页
this.$router.push('/login');
// 调服务接口的注销方法,真正注销
this.$axios.get('api/user/logout').then((r)=>{
    console.log('注销成功');
}).catch(e=> {
    console.error(e);
})

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

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

相关文章

Java基础之《netty(13)—任务队列taskQueue》

一、任务队列 1、用户程序自定义的普通任务 2、用户自定义定时任务 3、非当前Reactor线程调用Channel的各种方法 例如在推送系统的业务线程里面&#xff0c;根据用户的标识&#xff0c;找到对应的Channel引用&#xff0c;然后调用Write类方法向该用户推送消息&#xff0c;就…

基于java+springmvc+mybatis+vue+mysql的养老院管理系统

项目介绍 管理员后台页面&#xff1a; 功能&#xff1a;主页、个人中心、护工管理、家属管理、楼房资料管理、房间资料管理、床位管理、老人入住管理、老人档案管理、身体状态管理、用药情况管理、转房登记管理、外出登记管理、药品信息管理、药品入库管理、药品出库管理、物品…

【C语言】整型的存储方式(大小端,原码,反码,补码)

目录 一、基本类型 二、原码&#xff0c;反码&#xff0c;补码 2.1 原&#xff0c;反&#xff0c;补的计算方式 2.1.1 正数的原&#xff0c;反&#xff0c;补 2.1.2 负数的原&#xff0c;反&#xff0c;补 2.2 为什么要用补码存放 2.3 大小端是什么&#xff1f; 2.3.1 …

明道云联合契约锁共建人事场景电子签约解决方案

背景介绍 在每个组织的人事管理工作中&#xff0c;从招聘、入职、在职、调岗到离职&#xff0c;整个过程中存在大量的合同、证明、函件、通知等文件需要签字盖章。HR每天都要在“核对文件、敲章、通知员工签合同、催进度、给外地员工寄合同、关注合同到期时间等”繁琐的签署工…

使用vite和Element Plus,实现部署后不修改代码/打包,新增主题/皮肤包

Web前端界面切换主题/皮肤&#xff0c;是一个常见的需求。如果希望在打包部署后实现皮肤的修改甚至增加皮肤&#xff0c;不需要修改源码或者重新打包&#xff0c;类似于我们常见的皮肤包扩展&#xff0c;又该如何实现呢&#xff1f; 我使用类似上一期多语言包功能中介绍的方法来…

基于Xlinx的时序分析与约束(3)----基础概念(下)

1、4种基本的时序路径 下图是一张典型的FPGA与上游器件、下游器件通信的示意图&#xff1a; 其可以划分为4条基本的数据路径&#xff0c;这4条路径也是需要进行时序约束的最基本路径。 &#xff08;1&#xff09;寄存器到寄存器 路径2&#xff0c;FPGA内部的寄存器到另一个寄存…

[附源码]Node.js计算机毕业设计高校医疗健康服务系统的设计与实现Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

【C++初阶】类和对象(下)再谈构造函数、static成员、C++11的成员初始化新玩法、友元类、内部类

文章目录再谈构造函数static成员C11的成员初始化新玩法友元类内部类再谈构造函数 1.构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 虽然上述构造函数调用之后&#xff0c;对象中已经有了一个初始值&am…

客户管理系统如何提升体验

数字化时代&#xff0c;客户与企业交互的触点爆炸式增长&#xff0c;客户体验正从单一触点走向端到端旅程。众多的产品、海量的数据&#xff0c;导致客户对体验的要求越来越多......CRM客户管理系统是企业提升客户体验的有效工具&#xff0c;它不仅可以帮助您进一步了解客户&am…

App自动化之dom结构和元素定位方式(包含滑动列表定位)

先来看几个名词和解释&#xff1a; dom: Document Object Model 文档对象模型dom应用: 最早应用于html和js的交互。界面的结构化描述&#xff0c; 常见的格式为html、xml。核心元素为节点和属性xpath: xml路径语言&#xff0c;用于xml 中的节点定位&#xff0c;XPath 可在 xml…

javaSE - 三个常用的接口(Comparable,Comparator,Cloneable)

1、Comparable 英 [ˈkɒmpərəbl] 美 [ˈkɑːmpərəbl] 可比较的;可比的;可比性;可比;可比较   2、Comparator 美 [kəmˈpɜrətər] n. 比较器&#xff0c;比色器&#xff0c;比较电路&#xff0c;比长仪&#xff0c;场强计 3、 Cloneable 可复制的 一、Comparable …

MySQL性能优化浅析

1. 硬件 1.1 CPU IO密集型&#xff0c;提升CPU核心数 计算密集型&#xff0c;提升CPU频率 1.2 磁盘 机械硬盘在随机访问时&#xff0c;由于受磁针移动速度的限制&#xff0c;性能会大幅降低。使用固态硬盘可以大幅提升随机访问的能力。按需选择。 1.3 其他 带宽、内存频…

Superset 安装配置

文章目录Superset 安装配置一、Superset 概述1. Superset简介2. 功能概述3. 支持的数据库二、Superset 环境部署步骤三、创建虚拟机&#xff0c;安装CentOS1.下载CentOS2.创建虚拟机3.编辑虚拟机设置4.安装centos7.9mini版本5.启动centos&#xff0c;并进行登录四、CentOS配置1…

小米(Android)刷NetHunter安装指南

一、安装NetHunter 前提&#xff1a;确保手机已经root&#xff0c;已装上magisk。如果没有root&#xff0c;可用尝试magisk root 后执行此文 1、下载Nethunter&#xff1a;Get Kali | Kali Linux 然后push 到sdcard 里&#xff0c; 2、打开magisk&#xff0c;选择刚刚下好的…

Windows下安装libtorch与Clion配置

Windows 安装和使用libtorch 1.下载libtorch libtorch的下载链接&#xff0c;如下图所示&#xff0c;libtorch有release和debug版本可以选择。为了方便调试&#xff0c;下debug版。电脑上没CUDA&#xff0c;下次有需要再更新吧。 2.libtorch使用 在Visual Studio的使用可以参…

云原生周刊 | 让 ChatGPT 以电子邮件的方式来解释 KubeSphere

过去的一周是 ChatGPT 的狂欢&#xff0c;我猜每一位云原生玩家都很好奇他是如何看待 Kubernetes 的。咱们不防换个方式来提问&#xff0c;让它使用电子邮件的方式来向别人推荐 KubeSphere 和 OpenFunction。 开源项目推荐 Tailscale Ingress Controller 这是针对 Tailscale …

【DevOps实战系列】第七章:详解Docker私服Harbor篇

个人亲自录制全套DevOps系列实战教程 &#xff1a;手把手教你玩转DevOps全栈技术 Harbor私服搭建 讲完Nexus3再来看下harbor&#xff0c;其实大同小异&#xff0c;只不过harbor的管理要比Nexus3更专业、功能更完善&#xff0c;大家按需选择即可&#xff0c;Nexus的优势是他能和…

web网站工程项目前期需求分析与规划怎么写?

在当下&#xff0c;判断一份网站工程项目文档是否优秀&#xff0c;项目目录是最直接的体现&#xff0c;同时&#xff0c;工程说明、需求分析和项目规划各版块的内容都缺一不可。工欲善其事必先利其器&#xff0c;前期准备得越充分&#xff0c;后期就会越顺利。 本期&#xff0c…

Centos7安装图形化界面并使用Windows远程桌面连接(包含离线部署)

一、在centos7 中部署远程桌面所使用的程序 1、关闭防火墙和selinux(xrdp是通过3389端口远程桌面连接 ) [rootlocalhost ~]# systemctl stop firewalld #临时关闭防火墙 [rootlocalhost ~]# systemctl disable firewalld.service #永久关闭防火墙 [rootlocalhost ~]# setenf…

SpringMVC:SpringMVC之JSON数据传输参数(5)

JSON数据传输参数1 JSON数据传输参数2 JSON普通数组3 JSON对象数据4 JSON对象数组5 小结1 JSON数据传输参数 现在比较流行的开发方式为异步调用。前后台以异步方式进行交换&#xff0c;传输的数据使用的是JSON,所以前端如果发送的是JSON数据&#xff0c;后端该如何接收? 对于…