SSO(Single Sign On)
单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,同时这种实现是不需要管理员对用户的登录状态或其他信息进行修改的,这意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。这种方式减少了由登录产生的时间消耗,辅助了用户管理,是比较流行的。
https://baike.baidu.com/item/SSO/3451380
解决方案
解决方案
这里只是简单简述下我自己验证过的方案
1.CAS
CAS是Central Authentication Service的缩写,中央认证服务,一种独立开放指令协议。CAS 是 耶鲁大学(Yale University)发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。
待续
2. Spring Security 5.2 OAuth2 SSO
3. Sa-Token-SSO
Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。
https://sa-token.dev33.cn/doc/index.html#/
在官方文档中,直接定位到sso模块二,然后扩展到三
集成到真实项目
因为真实项目的鉴权中心使用的是Spring Security OAuth2 集成的,然后sa-token只是做了登录,然后进行模拟登录,内部还是使用原项目的鉴权.
前端改造
完整的内容
https://flowus.cn/share/88f4fa31-cc48-4a15-b671-328e79532372
【FlowUs 息流】SSO 解决方案
api.js
import request from '@/router/axios';
export const isLogin = () => request({
url: '/sa/isLogin',
method: 'get',
headers: {
"X-Requested-With": "XMLHttpRequest",
"satoken": localStorage.getItem("satoken")
}
})
export const getSsoAuthUrl = (row) => request({
url: '/sa/getSsoAuthUrl',
method: 'post',
params: {clientLoginUrl:row}
})
export const doLoginByTicket = (row) => request({
url: '/sa/doLoginByTicket',
method: 'post',
params: {ticket:row}
})
export const getUserInfo = () => request({
url: '/sa/sso/myinfo',
method: 'get',
})
export const ssoLogout = () => request({
url: '/sa/sso/logout',
method: 'get',
headers: {
"X-Requested-With": "XMLHttpRequest",
"satoken": localStorage.getItem("satoken")
},
})
路由添加
{
path: '/ssoLogin',
name: 'ssoLogin',
component: () =>
import( /* webpackChunkName: "page" */ '@/page/sso/sso-login'),
meta: {
keepAlive: true,
isTab: false,
isAuth: false
}
},
login.vue改造
在登录页面进行改造.
created() {
//注释掉原有的方法,替换成验证sso的方法
this.ssoInit();
// this.getTenant();
// this.refreshCode();
},
在methods 方法体中添加
ssoInit() {
//检查是否已登录
isLogin().then((res) => {
if (!res.data.data) {
this.$router.push({
path: 'ssoLogin',
query: {
back: 'http://localhost:1888/#/ssoLogin'
}
});
}
})
},
sso-login.vue
<template>
<div>
</div>
</template>
<script>
import {mapGetters} from "vuex";
import {doLoginByTicket, getSsoAuthUrl, getUserInfo} from "@/api/sso/sso";
export default {
name: "sso-login",
computed: {
...mapGetters(["website", "tagWel"])
},
created() {
this.getTicket();
},
methods: {
getTicket() {
var back = this.getParam2('back');
var ticket = this.getParam('ticket');
if (ticket) {
this.doLoginByTicket(ticket);
} else {
this.goSsoAuthUrl();
}
},
goSsoAuthUrl() {
getSsoAuthUrl(location.href).then((res) => {
location.href = res.data.data;
})
},
doLoginByTicket(ticket) {
doLoginByTicket(ticket).then((res) => {
localStorage.setItem('satoken', res.data);
//调用user-info
getUserInfo().then((res2) => {
var data = res2.data;
var loginForm = {tenantId: data.tenant_id,deptId:data.dept_id,roleId:data.role_id,username:data.user_name,password:'admin',key:'account'};
//到这儿其实就已经登录结束了.下面的方法是进行模拟登录因为这个项目的鉴权中心是
//Spring Security OAuth2 token不通用.参考原项目的登录页面就行,需要什么参数通过认证中心的userinfo接口返回即可.
this.$store.dispatch("LoginByUsername", loginForm).then(() => {
this.$router.push({path: this.tagWel.value});
loading.close();
}).catch(() => {
loading.close();
this.refreshCode();
});
})
})
},
getParam(name, defaultValue) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] == name) {
return pair[1];
}
}
return (defaultValue == undefined ? null : defaultValue);
},
getParam2(name) {
var query = window.location.href.split('?');
var vars = query[1];
var strings = vars.split('=');
if (name == strings[0]) {
return strings[1];
} else {
return null;
}
},
}
}
</script>
<style scoped>
</style>
vue.config.js
添加代理,在devServer方法体重
'/sa': {
//本地服务接口地址
target: 'http://localhost:9001',
ws: true,
pathRewrite: {
'^/sa': '/'
}
},
登出
在store 中user.js中找到登出方法
// 登出
LogOut({commit}) {
return new Promise((resolve, reject) => {
//原有方法的登录代码
//添加
ssoLogout().then(() => {
//website.ssoLogin 为了避免在这里写死,所有替换到统一的js中
//ssoLogin: 'http://localhost:1888/#/login'
location.href = website.ssoLogin
})
})
},
到这儿springcloud + vue 的项目就改造成功了.
还有一个springboot + vue admin element 改造案例
有待后续