koa和vue实现单点登录__前端__Vue.js
发布于 3 年前 作者 banyungong 1191 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

theme: cyanosis highlight: github

单点登录

postMessage Api地址

使用的是iframepostMessage的方式

主要用到的技术点:

  • vue
  • koa
  • jwt
  • mongodb
  • iframe+postMessage

实现单点登录的大体流程

  1. 创建一个ssoclient项目,这个项目只有登录功能。
  2. 创建一个ssoserver项目,后端项目提供登录接口验证。
  3. 创建一个companyclient项目,暂时只写前端。

代码实现

1、ssoclient项目

我们需要实现一个登录的功能,简单实现就好,本堂可的主要目的是了解如何进行单点登录。

封装请求api

安装axios 
yarn add axios 
npm install axios

util/request.js

import axios from "axios";

const _axios = axios.create({
  baseURL: '/api',
  timeout:10000
});

// 添加请求拦截器
_axios.interceptors.request.use((config)=> {
  // 在发送请求之前做些什么
  return config;
}, function (error) {
  // 对请求错误做些什么
  return Promise.reject(error);
});

// 添加响应拦截器
_axios.interceptors.response.use((response)=>{
  // 对响应数据做点什么
  let data = response.data;
  console.log(response)
  if(response.status === 200){
    return data;
  }
  return Promise.reject(data.msg);
}, function (error) {
  // 对响应错误做点什么
  return Promise.reject(error);
});

export default _axios;

全局挂载axios请求,main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from "./util/request";

Vue.config.productionTip = false
Vue.prototype.$axios = axios;

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

Login.vue

<template>
  <div>
    <input v-model="email" placeholder="请输入邮箱"/>
    <input type="password" v-model="password" placeholder="请输入密码"/>
    <button @click="toLogin">登录</button>
  </div>
</template>

<script>
export default {
  data(){
    return {
      email:'linlin@qq.com',
      password:'123456',
      redirectUrl:''
    }
  },
  created(){
    let search = window.location.search
    if(search == '' || !search.includes('?')){
      console.log('没有回调的URL')
    } else {
      let str = window.location.search.split('?')[1];
      console.log(str)
      this.redirectUrl = decodeURIComponent(str.split("=")[1]);
      console.log(this.redirectUrl)
    }
    
  },
  methods:{
    toLogin(){
      this.$axios({
        url:'/api/users/login',
        method:'post',
        data:{
          email:this.email,
          password:this.password
        }
      }).then(res=>{
        console.log(res)
        window.localStorage.setItem('token',res.token)
        if(this.redirectUrl){
          window.location.href = this.redirectUrl;
        } else {
          this.$router.push({name:'About'})
        }
      }).catch(res=>{

      })
    }
  }
}
</script>

vue.config.js

module.exports = {
  devServer: {
    open:true,
    port:'8000',
    proxy: {
      '/api': {
          target: 'http://localhost:8888/', //API服务器的地址
          ws: true,  // 代理websockets
          changeOrigin: true, // 虚拟的站点需要更换origin
          pathRewrite: {   //重写路径 比如'/api/aaa/ccc'重写为'/aaa/ccc'
              '^/api': ''
          }
      }
  },
  }
}

我们需要用koa搭建一个能登录,且能做token验证的服务器。

创建一个需要被单点登录的vue项目companyclient

ssoclient里添加postMessage发送消息

这段代码也可以改到vueRouter的全局守卫里。

export default {
  name: 'Home',
  beforeCreate(){
    //fromcompany需要用这个字段判断是否接收这个message消息,token是我们之前登录后存进去的
    window.parent.postMessage({from:'sso.com',token:localStorage.getItem('token')},'*')
  }
}

companyclient

新建一个token.js

util/token.js

这段代码其实可以写在vueRouter全局守卫里

window.addEventListener('message',function(e){
  console.log('iframe收到消息了')
  if(e.data.from === 'sso.com'){
    if(e.data.token){
      console.log(e.data.token)
      localStorage.setItem('token',e.data.token);
    } else {
      let redirectUrl = window.location.href
      location.href=`http://localhost:8000/login?redirectUrl=${redirectUrl}`
    }
  }
})

let iframe = document.createElement('iframe');
iframe.width = 0;
iframe.height = 0;
iframe.style.display = 'none'
iframe.src = "http://localhost:8000"

document.body.appendChild(iframe);

main.js里面引用

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './util/token'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: YaYa 原文链接:https://juejin.im/post/7012410335734792206

回到顶部