关于Who are you(身份认证)
回顾和整理下身份认证的一些知识点。
用户名/密码一次性验证
浏览器输入用户名/密码,服务端校验一次(用户名有效,密码匹配),通过后,跳转后续页面。
优点:除了简单,没有其他优点。
个人观点:一切的开始,后继者的起点,Respect。
- 类似服务器登陆,或者通俗点大门钥匙,一旦开门之后,屋内的东西就都是可见、可用的。
- 目前所有的Web认证体系,基本都是用户名/密码或者其变种。类似指纹、脸部等生物识别一类的,并未普及(痛点:隐私,数据量,特征变化同步)。
- 用户名/密码,关联性比较强的技术主要包括加密算法,加密传输等,基本都是围绕安全在扩展。
- 基本没有直接使用的,有了解到一些很有意思的用途,比如安全蜜罐。
通过Session实现生命周期管理
浏览器用户名/密码验证成功之后,服务端建立与客户端的全局唯一的会话Session,将Session ID写入客户端的浏览器Cookie,后续每次资源请求,都会验证Session是否存在,从而对登陆状态实现保持和控制,即用户登陆生命周期的管理。
优点:通过SessionID可以实现权限控制、登出操作等。浏览器天然支持Cookie。
个人观点:将用户的一次性登陆扩展为登陆状态,从而可以进行状态管理。
- Session信息本身存放在服务端,浏览器端存放SessionID,传输简单。
- Session属于独立信息,局部使用,不影响系统功能,同时可以随时失效,实现生命结束。
- Session/Cookie存在技术依赖,同时不跨语言。
- 目前常见的Session都是Web容器进行管理的,重启或者网络问题,会导致Session丢失。
- Cookie本身存在限制和安全问题(跨域,伪造,中间人)。
通过令牌(Token)实现客户端扩展
Session存在技术依赖,客户端的最大的限制是依赖浏览器的Cookie机制,因此对于手机,隐身模式或者多种多样的物联网不友好(支持)。所以可以使用一次性令牌(Token)来替代Session,进行登陆生命周期的管理,相应的需要服务层面实现相关的令牌服务。
优点:支持状态管理,权限管理,和Session逻辑一致,同时去除了基础技术依赖。
个人观点:Session理论的替换实现,功能覆盖,同时降低了客户端一侧的技术依赖(主要是Cookie)。
- 技术实现相对Session复杂了,有多种业内标准,需要做技术选型。
- 前后端需要进行编码实现,同时约定传输,一般是通过HTTP Header传输,需要面对中间人,重放等问题,一般结合签名,时间戳,https等使用。
- 对于服务端,Token的签发、校验、管理、存储,从Web容器级别提升为了系统服务,对服务的可靠性存在需求(超时,资源,算法,升级等)。
- Token校验是一个高频行为,存储读取层面,一般需要内存型缓存来支持(Ehcache,Caffeine,Redis)。
特殊Json Web Token实现服务端扩展
一般令牌(Token)是通过服务端的统一令牌服务进行签发,校验,管理,属于系统级别功能,当网站面对大流量时,令牌服务会面临资源压力,因此大佬们又发明了JWT,将部分信息放到Token中携带,使Token本身具有一定的业务含义,从而解耦最核心的签发和校验功能,并降级令牌服务。
优点:还是Token的性质,通过算法约定,解耦签发和校验过程,可以实现一个应用签发,其他应用校验,实现服务端扩展。
个人观点:Token的一种特殊实现,有得必有失。
- 实现了服务端Token服务的降级,提升可靠性。
- 设计了特殊的数据结构(header.payload.signature)。
- 因为携带了信息,所以安全上相比传统Token,有更高的要求。
- 因为服务端不需要存储令牌信息了,因此无法做到手动失效(logout功能),只能靠JWT本身的过期信息,不适用于需要全生命周期管理的场景。
- 实际上很不安全,在非https的情况下,任何人都可以拦截并看到payload的信息,所以在实际使用上,通常设置很短的失效时间,然后通过访问刷新/续期机制,不断的更换JWT(相同payload),来实现认证周期的延续性。同时因为生成/验证均在服务端,可以对JWT进行对称加密,进一步提升安全性。
- 网上所有用了JWT,然后又用REDIS等存储,来保存JWT,用来实现logout一类功能的,基本都是水货。JWT更适用于跨系统间的互通。
集团网站系统下的跨域
大集团系统往往包含多个子系统,相同的主域,但是不同的子域名,然后需要提供统一的登陆认证入口,实现多个子系统之间的一次性登陆(SSO)。因为浏览器同源策略,不同的子域,也属于跨域,所以针对这种情况的时候,可以通过认证服务对Cookie进行改写,实现Session的跨域可用。
优点:适用于对于没有令牌服务,基于Seesion的历史系统的改造,简单可靠,成本小。
个人观点:原理是Cookie+Session,不需要额外的令牌服务,不影响业务。
- 需要对Cookie改写。
- 需要对Session进行统一管理,或者叫分布式Session,主要分为Session复制(容器级别,Tomcat),Session统一存储(代码级别,Spring Session)。
- 资源,资源,资源
JWT的天然跨域
同样的跨域情况下,JWT的特性,提供了天然跨域+分布式
优点:扩展简单,SSO服务负责生成JWT,其他历史系统少量代码改造,增加拦截认证。
个人观点:对比Session,支持设备,支持跨主域,支持跨语言。
- 改造简单,通常增加一个统一的Filter就可以,不影响实际业务功能。
- JWT的问题一直都存在,特别是无法强制下线,如果需要每个系统实现访问续期的话,存在不少改造。
完整态的SSO
更完整一些的SSO,可以通过全局会话和子系统令牌来实现。
整体流程大致如下:
- 提供一个统一的SSO服务端(认证管理,令牌管理)
- 用户访问子系统,检查是否有Token/校验Token,没有的话跳转SSO系统,并携带子系统地址
- SSO判断用户是否存在全局对话,不存在跳转登陆页,存在的话新增子系统、生成Token
- 通过用户名+密码登陆SSO系统,SSO系统创建用户全局会话Session
- SSO通过判断子系统地址,注册/新增子系统登陆状态,并生成子系统Token
- SSO系统携带Token,跳转子系统地址
- 子系统检测到传入Token,调用SSO服务验证有效性,并返回到客户端
- 客户端使用Token与子系统进行交互
- logout时,SSO系统删除全局会话,后续子系统Token校验失败,跳转登陆
优点:通过两层管理(全局会话+局部令牌),实现统一管理和子系统管理。
个人观点:
- 引入了令牌服务(生成,验证,下发),系统复杂度较高。
- 局部令牌,可以根据实际情况约定范围,例如子系统已经存在令牌服务的,或者使用Session认证的,局部令牌可以只存在SSO系统与子系统之间,不需要暴露到客户端,子系统需要建立自身令牌与局部令牌的绑定关系。
- 局部令牌的验证和生命周期,可以统一由SSO系统完成,也可以下放子系统管理。
- SSO是单点认证的基本思路,实际实现的方式可调整的很多,例如CAS,SAML,OAUTH等等,代码层面Spring Security基本都支持,例子很多。
- 很多时候,尤其很多半懂不懂的,会把认证(authentication)和鉴权(authorization)混淆,狭义的SSO是为了认证的,鉴权常见的是RABC来完成。这种混淆会出现的一个很大的原因,是当需要独立出一个统一的认证服务的时候,通常也需要对权限进行统一的管理,所以常见的SSO在实现时,例如SAML,OAUTH2,都是包含了认证和鉴权两部分,但实际两部分是独立存在的,所以进行SSO系统建设的时候,一定要分清楚这两者的区别,多系统集成的时候,统一鉴权的复杂度要比统一认证高很多个Level,有兴趣的可以进一步了解下SSO系统中的idP和SP。
本文由 Ivan Dong 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Jun 13, 2023 at 10:11 am