要求:登录校园门户网站A后,可以免登录认证进入系统B。作为B方,我们借助cas框架实现单点登录。
背景:在原先正常登录的项目追加一个单点登录,所以我的逻辑代码都在casLoad页面。如果只是单点登录,完全可以写在login页面。
故当前项目:测试登录地址http://xxx.xx.xx.x:3000/#/login 单点地址为http://xxx.xx.xx.x:3000/#/casLoad
总体流程:
① 访问B系统单点登录页面检测到未登录,需要先跳转到cas认证中心(A)登录,获取票据。
跳转链接为cas认证中心登录地址,并携带上service参数,参数值为当前页面的encode编码值
② cas认证中心登陆成功后,会回传新的地址:单点地址+ticket票据(单点地址是对接时协商好的)。
③ B系统拿到票据后验证是否有效,若有效,可接着获取用户认证信息。
实现过程:
1. 路由守卫修改
router.beforeEach((to, from, next) => {
const isLogin = sessionStorage.flag == 1 ? true : false;
// 保留原登录页面,添加新单点登录页面
if (to.path == "/casLoad" || to.path == "/login" || to.path == "/register") {
next();
} else {
isLogin ? next() : next("/casLoad");
}
});
2. casLoad页面:页面只有一个loading样式
① 如果当前已登录,该干嘛干嘛
mounted() {
if (sessionStorage.getItem('flag') == 1) {
this.$router.push('/index') // console.log('要去首页');
} else {
}
},
② 如果当前未登录,判断当前页面地址是否有ticket参数,没有就要去认证中心;有就要验证ticket是否有效
mounted() {
if (sessionStorage.getItem('flag') == 1) {
this.$router.push('/home') // console.log('要去首页');
} else {
this.href = window.document.location.href // console.log(this.href);
if (this.href.includes('ticket=')) {
this.backToBLogin()// A登录后回B loading及提示 验证票据
} else {
this.initToALogin()// 去A登录 loading及提示 跳转携带参数处理
}
}
},
methods: {
initToALogin() {
this.loadingText = "正在访问门户A,请稍等..."
this.getLoaingShow()
const url = encodeURIComponent('http://xxx.xx.xx.x:3000/#/casLoad')
window.location.href = `https://xxx.xx.xx.x/cas/login?service=${url}`
},
backToBLogin() {
this.loadingText = "正在访问系统B,请稍等..."
this.getLoaingShow()
const ticket = this.href.split('ticket=')[1].split('#')[0]
this.validateTicket(ticket)
},
getLoaingShow() {
this.loading = this.$loading({
lock: true,
text: this.loadingText,
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
target: document.querySelector("#table"),
customClass: 'selfLoad',
});
},
destroyed() {
if (this.loading) {
this.loading.close();
}
}
出现问题:正在访问门户A 《=》正在访问系统B 的页面会交替重复出现
可能原因:部分门户A但不属于B的用户,在A处登录后来到B,验证B返回非200,于是又返回A,但是A认为成功登录又来到B......
最终解决:对validateTicket接口做错误处理,关闭遮罩,提示非法用户。