Single sign-on (sso)
PostMessage Api address
Iframe and postMessage are used
Main technical points used:
- vue
- koa
- jwt
- mongodb
- iframe+postMessage
The general process for implementing single sign-on
- Create a sSOClient project that has only login functionality.
- Create an SSOServer project with the back-end project providing login interface authentication.
- Create a CompanyClient project and write only the front end for now.
Code implementation
1. Ssoclient project
We need to implement a login function, simple implementation is good, the main purpose of this lesson is to understand how to conduct single sign-on.
Encapsulating request API
Install axios yarn add AXIos NPM install axiosCopy the code
util/request.js
import axios from "axios";
const _axios = axios.create({
baseURL: '/api'.timeout:10000
});
// Add request interceptor
_axios.interceptors.request.use((config) = > {
// What to do before sending the request
return config;
}, function (error) {
// What to do about the request error
return Promise.reject(error);
});
// Add a response interceptor
_axios.interceptors.response.use((response) = >{
// What to do with the response data
let data = response.data;
console.log(response)
if(response.status === 200) {return data;
}
return Promise.reject(data.msg);
}, function (error) {
// Do something about the response error
return Promise.reject(error);
});
export default _axios;
Copy the code
Globally mount the AXIos request, 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')
Copy the code
Login.vue
<template>
<div>
<input v-model="email" placeholder="Please enter email address"/>
<input type="password" v-model="password" placeholder="Please enter your password"/>
<button @click="toLogin">The login</button>
</div>
</template>
<script>
export default {
data(){
return {
email:'[email protected]'.password:'123456'.redirectUrl:' '}},created(){
let search = window.location.search
if(search == ' '| |! search.includes('? ')) {console.log('URL with no callback')}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>
Copy the code
vue.config.js
module.exports = {
devServer: {
open:true.port:'8000'.proxy: {
'/api': {
target: 'http://localhost:8888/'.// Address of the API server
ws: true./ / agency web sockets
changeOrigin: true.// Virtual sites need to change origin
pathRewrite: { // Rewrite paths such as '/ API /aaa/ CCC 'to '/aaa/ CCC'
'^/api': ' '}}},}}Copy the code
We need to use KOA to build a server that can log in and do token authentication.
Create a VUE project companyClient that requires single sign-on
Add postMessage to sSOClient to send messages
This code can also be changed to vueRouter’s global guard.
export default {
name: 'Home'.beforeCreate(){
// FromCompany needs to use this field to determine whether to receive the message. The token was saved after we logged in earlier
window.parent.postMessage({from:'sso.com'.token:localStorage.getItem('token')},The '*')}}Copy the code
companyclient
Create a new token.js file
util/token.js
This code could actually be written in the vueRouter global guard
window.addEventListener('message'.function(e){
console.log('Iframe has received the message')
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);
Copy the code
Reference in 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')
Copy the code