网站首页 > 知识剖析 正文
提要
SSO统一认证现在属于传统必备技能,很多人都花了很大段的话去描述这个过程,感觉不够极客,有水过程拔高的嫌疑,这里我先划分几种场景和情况
- 负载均衡衍生方案(seesion或者cookie固化存储方案)
- cas票据认证(Service Ticket,属于偏服务端的解决方案)
- sso一次登录多应用通行(偏前端,但其实cas也是sso实现的方案,这里区分来说,主要只现代常用)
- 授权登录(微信授权确认认证、第三方授权登录)
- 域认证方案(多见于大网区域划分,属网络安全方案)
- nginx同域代理方案(同源策略)
过程
当前划分的几种方式其实是随着技术路线的发展在发展的
- 负载均衡衍生方案 这套方案多常见于.net,因为有session固化存储进sqlserve数据库的方式,能够有效解决多个应用共享coocie或者session会话的标识,之前的场景多为单系统,因技术处理其他语言没有对应的解决方案去处理,所以应用范围多仅限于负载均衡时coocie服务端会丢失的问题,将相关的网站整站负载均衡处理,不需要改动其他代码即可完成,而且不管是服务端渲染还是前后端分离方式都能够支持,硬性要求就是服务端必须统一为C#,有极大的弊端,但优越在配置简单,破坏性弱。
- cas票据认证 此场景属于token认证之前的一个解决方案,在服务端去处理网站或者接口的认证,常见于前后端未分离的项目如jsp、asp但不仅限与此,前后端分离也支持,区别在于服务端为有状态服务,必须要求有一个票据生成端,各个服务端去集成相关票据服务提供的插件,其实也就是解决了跨语言的问题,如果套到token上也是可行的。
- 优势:
更安全的判断,更灵活的路由授权机制,那些访问路径下屏蔽认证、那些路径下需要很灵活
相较于sssion方式不容易丢失凭证 - 劣势
需要单独配置票据服务
集成客户端对一些诉求比较特殊的系统,配置复杂度较高,兼容自有逻辑时需要很密集的处理,牺牲了票据的同步性,很容易产生重复跳转,304常常伴飞
针对前后端分离方案,可能得页面端也附加一些逻辑以满足具体要求
- sso一次登录多应用通行 随着前端的工程化、生态化,IE6-9的封印被解除后,人们对美的追求有点儿收不住,历史项目逐渐被清出,多数sso趋向从openid第三方授权认证找到的灵感,思路有些雷同,(有差异,免杠精)只不过把其中确认页换成了自动的,在加上无状态接口请求的盛行,人们更喜欢用token的认证形式去代替coocie或者session这种形式,更进一步放大接口分布式的能力,其实变相的是把存储由服务端放到了前端
- 授权登录(微信授权确认认证、第三方授权登录) 盗个图说明以下,这个授权认证相信搞过多个平台认证的都很熟悉,本质上有点儿脱胎于cas与前端处理的结合
- 域认证方案 域认证这个属于比较古老的方案,属于电脑机器账号密码登录,权限划分等多为电脑的域权限划分,属于pc应用的产物,(网关、网络管理员)
- nginx同域代理方案 能够把公共的coocie信息共享给其子服务使用,属于快速备选方案,很容易适配两个不同的系统
优化处理
从应用型我主要介绍现在sso在前端部分去处理主跳转逻辑的思路 传统的思路网上介绍很多,但绕不开一个问题
- token服务端没办法去存储区分token的值,也就是说,每次必须去传token,如果不传token,服务端是没办法用其他标识去识别客户端标识的(ip、机器码等都有弊端或者花销大),ip在网络环境复杂的情况下,区分内网,外网风险太大,mac地址获取客户端ActiveX插件式获取体验和兼容性问题明显。
- 因此前端解决的方案主要解决的一个核心问题是,保证每次都能传递token,页面参数传递这种方式,体验差且也很容易在初期服务逻辑不健全和稳定时反复跳转,问题排查艰难
基于以上的点,我们主要解决的核心问题放在了跨域时,排除url传递,如何传值的问题,因此有了postmessage跨域传值方案,且已经过线上验证,不会存在页面跳转的问题,最多只有一次自刷新逻辑。 统一认证页面下附加的token交换页,用于传递值,如果安全考量,可以把*换成指定的ip段 子应用端,(主判断逻辑最好是提供好的逻辑处理,便与后期统一调整) 由此以下的完整客户端逻辑实现如下:
function getTokenInfo(redirectUrl){
// 注册消息事件监听,接受子元素给的数据
window.addEventListener('message', (e) => {
var token=e.data;
if(token){
localStorage.setItem('token', token);
document.body.removeChild(document.getElementById('if'));
//刷新
location.reload();
}else{
const path=publicWay;
const newRedirectUrl = `${path}/#${
'/login'
}`
window.location.href = newRedirectUrl + '?redirect=' + redirectUrl
}
}, false);
if(!document.getElementById('if')){
var iframe = document.createElement('iframe');
iframe.style.cssText = 'display:none;';
iframe.src = `${publicWay}/token.html`
iframe.height = 0
iframe.width = 0
iframe.id = 'if'
document.body.appendChild(iframe)
}
}
/**
* 单点登录
*/
const loginAuth = (redirectUrl, loginedcallback) => {
console.log('-------单点登录开始-------')
// 用户中心根据用户获取数据接口
var path = `${config.casPrefixUrl}/api/auth/user-info`
let token
const paramTokenReg = new RegExp('(^|&)token=([^&]*)(&|$)', 'i')
const regExpMatchArray = window.location.search.substr(1).match(paramTokenReg)
token =
regExpMatchArray != null
? decodeURI(regExpMatchArray[2])
: localStorage.getItem('token')
token = tokenReg.test(token) ? token : '' // ;
/** */
// getTokenInfo
if(!token){
getTokenInfo(redirectUrl);
}else{
//有数据结果才调用
const request = new XMLHttpRequest()
request.open('GET', path + '?token=' + token, true)
request.send()
request.onreadystatechange = function() {
// 请求成功返回数据并解析
if (request.readyState === 4 && request.status === 200) {
/**
* 如果正常返回了数据,则回调处理
* 登录成功后获写入token,仅写入有效token
*/
if (token!=localStorage.getItem('token')) {
localStorage.setItem('token', token);
// const url=location.origin +location.pathname+location.hash+location.search.replace(/&?token=[^&]*/,'');
// location.replace(url);
}
if (loginedcallback) {
const { data } = JSON.parse(request.responseText)
loginedcallback(data)
}
}
// 未登录时,接口返回401,
if (request.readyState === 4 && request.status === 401) {
const path=publicWay;
const newRedirectUrl = `${path}/#${
'/login'
}`
localStorage.setItem('token','');
window.location.href = newRedirectUrl + '?redirect=' + redirectUrl;
}
}
}
console.log('-------单点登录结束-------')
}
复制代码
总结
技术的发展往往根据既有的规律去升级,不会凭空捏造,无中生有,实践出真理,对做技术的更是这样,你只有真正的遇到了既有的问题,剪除了其他旁支,才能得出你最期待的结果
往期目录
- 35岁鞋不合脚的问题
- 组态,你值得拥有
- GB级word文档预览方案
- 多平台博客工具推荐
- 全栈终结者-把nuxt扔进垃圾桶、Blazor与seo的化学反应
- ol与Vue室内定位模式设计
- 二十余年如一梦,此身虽在堪惊。闲登小阁看新晴。古今多少事,渔唱起三更
- Tauri操作实战(1)-环境准备
- 代码生成代码
- webpack5 针对vue vue-cli-service 升级指南(三)
- webpack5 针对vue vue-cli-service 升级指南(二)
- webpack5 针对vue vue-cli-service 升级指南(一)
PS
最近又进入万金油状态,乱七八糟什么东西都在整,焦虑突从心起,无伤大雅,很快调整了,不管做什么,都是我技术路上的柴火,强大的内心不被挫败,坚持我们的代码梦想、技术YYDS!!!
---- 老哥们加油,不要被一时的挫败和人影响,我中二的标题图又来了,哈哈哈!
猜你喜欢
- 2024-11-24 浏览器跨域问题以及常用解决方案
- 2024-11-24 14个前端小知识,我猜你每天都会遇到
- 2024-11-24 跨域问题的4种解决方案
- 2024-11-24 什么是跨域?跨域解决方法
- 2024-11-24 构建rancher自定义ui的前端镜像
- 2024-11-24 你应该知道的前端小知识,初学者,确定不点进来看看吗?
- 2024-11-24 15个前端小知识
- 2024-11-24 记一场纯JS赛——DiceCTF2021 Web题解
- 2024-11-24 如何基于 Elasticsearch 实现排序沉底或前置
- 2024-11-24 如何查找网站源IP地址
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)