目录
3、密码式(Resource Owner Password Credentials)
前言
用户登录(身份认证、权限管控)是应用系统的基本能力。应用服务要知道当前是谁在使用系统,现实世界中的人要向虚拟世界证明自己的身份。最简单手段就是双方约定一个独一无二的口令(龙门飞甲,便知真假),即用户名+密码。因为用户名密码只有用户自己和服务系统知道,通过判断这两个信息的有效性,服务器才能知道你就是你。口令不能够每次见面都讲一次,因为讲得越多,非常麻烦且泄露的风险就越高,于是便有了token(一段时间有效,可以代替口令)。同时了保证安全性,整个验证过程会加入很多加密手段(传输加密、存储加密、多次错误锁定、密码强度校验、双因素验证等)。同时还会加入图片验证码来防止暴力破解,验证码从最早的数字+干扰线模式开始一路发展出很多形态,如汉字识别、数学公式、图形判断、滑块等等。验证码技术的升级增加了服务的安全性,但也降低了用户体验,反面教材中以12306抢票系统为首,受到网友万人吐槽实属业内独一份。
随着时代的发展,人们越来越依赖手机,同时手机号也基本实现了实名制,基于手机的登录模式占比越来越高。 最常见的就是 手机号 + 短信验证码登录,该模式是目前应用最为广泛的登录方式之一。
还有由运营商提供的sim卡登录服务:
该模式通过系统限制短信验证码的触发频率,可以淘汰图形验证码这一反人类元素(部分系统仍然保留了),用户仅需输入手机号码,带来了极大的便利性,大有一统天下的趋势。
再后来出现了一些生物识别技术,如指纹、面部识别等等。这些认证手段解决了最原始的身份认证问题,但随着时代的发展,信息系统越来越庞大,分布式高可用的微服务体系大行其道。各个系统之间紧密通讯,但又相互独立。跨系统、跨平台之间的身份认证变得非常必要,于是便有了SSO。
一、SSO简介
百科:单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统
要实现SSO,需要构建以下两个主要内容:
1、所有应用系统共享一个身份认证系统
需要有一个集中的认证系统,这个认证系统要完成以下几个基本工作:
- 存储和维护所有的用户信息,用户信息的增删改查,密码修改重置,用户冻结解锁等
- 完成登录认证,下发token的
- 验证token的有效性
为了保持大型系统的灵活性,用户信息必要时允许下发给子系统存储,但增删改操作只能在中心认证系统执行,执行完通过某种途径同步给子系统(一般是消息队列)。子系统本地存储的数据仅能做信息查询,并保持和中心服务器的通讯,以保证用户信息的时效性。
2、所有应用系统能够识别和提取当前登录用户的token信息
在SSO的场景下,当用户在身份认证系统完成登录操作后,后续所有的系统间交互都是基于认证系统下发的token来进行了。下游系统应该可以获取token,发送请求时携带token,并可向认证系统进行token有效性的校验。
SSO优缺点
优点:
- 用户一次登录,多端访问,提高了用户使用的效率
- 独立的认证系统,简化了应用程序开发,提高了开发人员效率
- 用户信息集中维护,简化了管理,提供了运营人员效率
- 便于构建大型分布式系统
缺点:
- 系统复杂度提升,开发和维护成本高,小型项目不适用
- 因可能牵扯太多下游系统,不利于重构,需尽可能保证兼容性升级
- 部分敏感系统可能被过度暴露(可通过敏感内容可做二次身份确认避免该问题)
二、OAuth2简介
百度百科:
OAuth2.0是OAuth协议的延续版本,但不向前兼容OAuth 1.0(即完全废止了OAuth1.0)。 OAuth 2.0关注客户端开发者的简易性。要么通过组织在资源拥有者和HTTP服务商之间的被批准的交互动作代表用户,要么允许第三方应用代表用户获得访问的权限。同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。2012年10月,OAuth 2.0协议正式发布为RFC 6749 [1] 。
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。
OAuth2.0很可能是下一代的“用户验证和授权”标准。现在百度开放平台,腾讯开放平台等大部分的开放平台都是使用的OAuth 2.0协议作为支撑。
RFC 6749: The OAuth 2.0 Authorization Frameworkhttps://www.rfc-editor.org/rfc/rfc6749
简单说OAuth2是一种授权框架,提供了一套详细的授权机制。应用于三方系统的登录认证,比如我们常用的微信登陆、支付宝登录。
一般包含这样一个过程:
1、主系统存储了所有的用户、账号、密码等敏感信息,在主系统完成登录后,允许跳转到预先和主系统对接过的第三方子系统。
2、子系统本来是没有用户、账号、密码信息的,在主系统登录跳转过来后,会通过某种约定的机制,传递一个令牌过来。
3、子系统凭借该令牌可以请求主系统,获取用户信息(一般不包含密码)。子系统一般会选择在本地再存储一份用户信息
令牌是有时间限制的,过期后需要刷新令牌或者重新申请令牌。不同于普通的登录授权,oauth下发的令牌一般只能访问特定的部分资源,通常是和用户信息相关的。使用oauth2的前提是,子系统已经在主系统(即认证服务提供方)报备过,并得到了用于标记唯一系统身份的 客户端 ID(client ID)和客户端密钥(client secret)。
三、OAuth 2.0 规定了四种获得令牌的流程
这四种模式实现过程和使用场景都不相同,但其实都是通过使用事先约定的信息,向主系统获取一次授权的令牌,后续所有的系统交互还是基于这个令牌来操作的。子系统获得令牌后,通过接口请求到需要的信息(用户信息),之后一般还会在子系统后台完成初始化用户、权限配置、登录等隐藏操作。
1、授权码(Authorization Code)
该模式是使用最广,安全级别最高的模式,适用于拥有前后端的应用授权。一般讲到oauth对接都指的是这种模式。大家日常使用最多的微信登录和支付宝登录都是基于这种模式实现的。在这个过程中,code是主系统通过redirect_uri + 参数传递给子系统的,token是子系统发起后端post请求得到的。
微信登录:
1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站(redirect_uri),并且带上授权临时票据 code 参数;
2. 通过 code 参数加上 AppID 和AppSecret等,通过 API 换取access_token;
3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
支付宝登录:
接入指南 | 网页&移动应用支付宝文档中心https://opendocs.alipay.com/open/01emu5
2、隐藏式(Implicit)
适用于只有前端,没有后端的应用。
1、三方系统向主系统发起授权请求: https://xxx.com/oauth/authorize?client_id=CLIENT_ID&redirect_uri=CALLBACK_URL
2、主系统收到请求后,校验收到的 CLIENT_ID 和 CALLBACK_URL 与系统内预留的信息是否一致
3、校验通过后主系统直接重定向到redirect_uri ,将令牌作为redirect_uri 参数,通发令牌给三方系统,隐藏了授权码这个步骤。
https://CALLBACK_URL#token=ACCESS_TOKEN
这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。
3、密码式(Resource Owner Password Credentials)
直接把用户名和密码告诉第三方系统,第三方系统拿着账号、密码、客户端 ID(client ID)来发起http请求,主系统直接返回包含令牌的JSON 数据。该模式会产生很多安全问题。用户账密多端存储,容易产生数据不一致问题,也增加了信息泄露的风险
对于受信任的系统之间,如果选用该方式对接,应尽可能走内网接口。如暴漏在公网,应做好数据传输的加解密工作。
4、客户端凭证(Client Credentials)
客户端凭据模式主要应用于后端系统之间的通信,没有用户参与的场景。比如某些开放平台,允许注册应用获取一些平台公共资源,比如平台的介绍信息,注册应用本身的信息,这些理论上是不需要用户进行授权的,而且也跟用户没有归属关系,这个时候就可以使用此模式。三方系统只需要携带客户端 ID(client ID)和客户端密钥(client secret)来发起http请求,主系统直接返回包含令牌的JSON 数据。
四、OAuth2是不是SSO?
OAuth2的实现到底是不是单点登录呢,这个问题答案是比较模糊的,简单地说是或者不是回答都不够准确。但目前我们一般讲到OAuth2,都会比较普遍的认为他是属于单点登录的。
oauth侧重于解决主服务集群与另外一个不属于互相信任的应用群(通常由另一个公司提供的服务),第三方系统间的认证问题。通常各系统不在同一个域下,也不要求在同一个部署资源池内,只要求三方系统和认证系统公网相通即可。
而一般讲到的单点登录更注重于服务端和接入的客户端都在一个互相信任的应用群内(通常是同一个公司提供的不同子系统),各个子系统的用户属于单点登录服务端的官方用户,系统大多在同一个域下且内网相同。
五、JWT和OAuth
Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。
简单地说jwt是一种token的生成规则,这个token包含了部分用户信息,同时带有自签名和过期时间。自签名可以防止信息篡改,过期时间可以控制token有效期。这和oauth完全是两个概念的东西,没有可比性。
一串完整的JWT由三段落组成,每个段落用英文句号连接(.)连接,他们分别是:头部(Header)、负载(Payload)、签名(Signature),所以JWT内容格式是这样的:AAA.BBB.CCC。其中Header和Payload是用base64UrlEncode编码的,一般如果未做额外加密,是可以直接通过base64解码后阅读内容的。Signature是以Header和Payload为基础,使用密钥(仅服务器知道,绝对不可泄漏)通过加密算法(具体哪种算法在header中会写明)计算得出。因此jwt token一旦颁发,Signature便是固定值。token内的任何信息被修改,都会导致Signature的不一致,确保了token无法被伪造和修改。
Signature = HmacSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)
以下是一段示例jwt,密钥是:admin123456
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjpbeyJuYW1lIjoi5byg5LiJIn0seyJhZ2UiOiIxOCJ9XSwiaWF0IjoxNjY3OTk1MDQ1LCJleHAiOjE2Njc5MjMxOTksImF1ZCI6IiIsImlzcyI6IiIsInN1YiI6IiJ9.8AV7MJplq_jHt3juYE5v4yzAJJm6zJ7QB7qxgqo637E
Header:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
base64解码后:{"alg":"HS256","typ":"JWT"}Payload:eyJkYXRhIjpbeyJuYW1lIjoi5byg5LiJIn0seyJhZ2UiOiIxOCJ9XSwiaWF0IjoxNjY3OTk1MDQ1LCJleHAiOjE2Njc5MjMxOTksImF1ZCI6IiIsImlzcyI6IiIsInN1YiI6IiJ9
base64解码后:
{"data":[{"name":"张三"},{"age":"18"}],"iat":1667995045,"exp":1667923199,"aud":"","iss":"","sub":""}
工具网站
在线Base64编码加密解密还原工具- ToolTT在线工具箱
六、CAS
百科:CAS是Central Authentication Service的缩写,中央认证服务,一种独立开放指令协议。CAS 是 耶鲁大学(Yale University)发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。
协议特点
1、开源的企业级单点登录解决方案。
2、CAS Server 为需要独立部署的 Web 应用。
3、CAS Client 支持非常多的客户端(这里指单点登录系统中的各个 Web 应用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等语言编写的各种web应用。
4、CAS属于Apache 2.0许可证,允许代码修改,再发布(作为开源或商业软件)。
CAS是开源的SSO方案中最有影响力的,在github上的热度非常高。
官网:CAS | Apereohttps://www.apereo.org/projects/cas
架构图:
CAS服务器是基于Spring Framework构建的Java servlet,其主要职责是通过签发和验证票据来验证用户并授予对支持CAS的服务(CAS客户端程序)的访问权限。
CAS客户端是一个软件包,可以与各种软件平台和应用程序集成,以便通过某些身份验证协议(例如CAS、SAML、OAuth)与CAS服务器通信。
客户端通过几种受支持的协议中的任何一种与服务器通信。除了自己的CAS协议外,市面上主流的基本都支持,如SAML、OpenID Connect、OpenID、OAuth 2.0等。
cas协议过程:
CAS URIs:
七、OpenID
百科:OpenID 是一个以用户为中心的数字身份识别框架,它具有开放、分散性。OpenID 的创建基于这样一个概念:我们可以通过 URI (又叫 URL 或网站地址)来认证一个网站的唯一身份,同理,我们也可以通过这种方式来作为用户的身份认证。
OpenID是一个去中心化的网上身份认证系统。对于支持OpenID的网站,用户不需要记住像用户名和密码这样的传统验证标记。取而代之的是,他们只需要预先在一个作为OpenID身份提供者(identity provider, IdP)的网站上注册。OpenID是去中心化的,任何网站都可以使用OpenID来作为用户登录的一种方式,任何网站也都可以作为OpenID身份提供者。OpenID既解决了问题而又不需要依赖于中心性的网站来确认数字身份。
OpenID的理念和CAS正好相反,CAS强调中心化,OpenID强调去中心化。OpenID协议提供了一个基本的认证机制。
OpenID身份提供者(identity provider, IdP):何人都可以建立一个网站提供OpenID验证服务
OpenID 客户端:就是集成了 OpenID 登录服务的应用系统。
应用系统可以是单一的身份提供者,也可以是单一的客户端,也可以既是提供者又是客户端。
OpenID的理念非常先进,他幻想着所有厂家之间都保持着足够的友好性、开放性和兼容性,大厂和小厂之间可以平等对话,大家共同构建一个无障碍的身份识别体系。你可以使用某一网站的帐号去登录另一网站,只要这些网站都是实现了OpenID的服务。这一理念对用户非常友好,但在现实世界却寸步难行,国内系统基本上看不到。
1、虽然人人都可以是身份提供者,但能够提供高质量、长期、稳定的服务必然是少数大厂。到最后所谓的去中心化,也还是会变成中心化。
2、哪个应用系统不想沉淀自己独有的用户群体呢?各厂家之间怎么可能会互相信任呢?支付宝、微信这种大佬系统上永远不会出现三方登录的入口。大家都在构建属于自己的帝国。
需要强调一点,OpenID只管身份认证,不做资源授权管理。OpenID2.0使用了XML和自定义消息签名,开发人员有时很难做到这一点。
八、OIDC
OpenID Connect (OIDC) 是第三代OpenID技术,扩展了 OAuth 2.0 授权协议,在OAuth2.0上构建了身份层,使其可用作身份验证协议。 OIDC 通过一个称作“ID 令牌”的安全令牌在支持 OAuth 的应用程序之间启用单点登录 (SSO)。
OpenID(认证)+OAuth 2.0(授权)=OpenID Connect(认证+授权)。
使用标准的JWT令牌,REST/JSON消息流,允许开发人员跨网站和应用程序验证其用户,而无需拥有和管理密码。OpenID Connect的设计支持web程序、本地应用程序和移动应用程序。
Certified OpenID Connect Implementations | OpenID
完整的协议包含以下部分,其中Core是最小核心:
OpenID Connect Core 1.0规范定义了核心OpenID Connect功能:基于OAuth 2.0构建的身份验证,以及使用声明来传递有关最终用户的信息。它还描述了使用OpenID Connect时的安全和隐私注意事项。
核心步骤:
1、RP(接入的客户端 Relying Party)向OP(认证服务提供端 OpenID Provider)发送请求。
2、OP验证用户并获得授权。
3、OP使用ID令牌和访问令牌进行响应。
4、RP可以向UserInfo端点发送带有访问令牌的请求。
5、UserInfo端点返回有关最终用户的声明。
OpenID Connect对OAuth 2.0进行的主要扩展是ID令牌数据结构(JWT),以下为一个例子,标红的为必需:
{ "iss": "https://server.example.com", //颁发者的URL,https "sub": "24400320", //唯一标识 "aud": "s6BhdRkqt3", //OAuth 2.0 client_id "nonce": "n-0S6_WzA2Mj", "exp": 1311281970, //过期时间 "iat": 1311280970, //JWT下发时间 "auth_time": 1311280969, "acr": "urn:mace:incommon:iap:silver" }
阿里的OIDC:
OIDC_应用身份服务-阿里云帮助中心
https://help.aliyun.com/document_detail/174228.html
微软的OIDC:
九、SAML 2.0
安全断言标记语言(英语:Security Assertion Markup Language,简称SAML)是一个基于XML的开源标准数据格式,它在系统之间交换身份验证和授权数据,尤其是在身份提供者和服务提供者之间交换。SAML解决的最重要的需求是Web端应用的单点登录,目前能见到的基本都是最新版本 2.0 。
协议古老且内容庞大, 特点是使用xml传输,SP(Service Provider)和IDP(Identity Provider)之间不直接通讯,而是通过用户的浏览器进行两次重定向完成认证跳转。
十、LDAP
轻型目录访问协议(英文:Lightweight Directory Access Protocol,缩写:LDAP)。是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式的目录信息。LDAP起源于上个世纪,延续至今在企业内部(OA、ERP)的地位依然牢不可破。一个常用用途是单点登录,用户可以在多个服务中使用同一个账密,常用于公司内部网站的登录认证。
Ldap中文网 – ldap安装部署、使用技巧http://www.ldap.org.cn/简单地说:
1、DAP是一个协议(X.500),LDAP是他的一个轻量级变种协议
2、LDAP(轻型目录访问协议)是一种目录访问协议,而目录信息是存储在目录数据库内的。实现了LDAP协议的目录数据库有很多,其中最出名、影响最广的就是 Microsoft Active Directory。除此之外,还有Sun one Directory、IBM directory server。以及开源的openldap(OpenLDAP, Main Page)、Apache Directory LDAP(Welcome to Apache Directory — Apache Directory)。
3、我们常说的LDAP服务器,是指部署了某一目录数据库(如微软的Active Directory)的应用服务器,该服务器对外提供LDAP服务。
4、目录数据以树形结构存储,不支持事务,读性能远大于写性能。
目录数据库由服务端和客户端组成,这一点和我们常用的关系型数据库(mysql)一样。但不同的是,LDAP数据库的客户端和服务端通讯是遵循标准的LDAP协议的,故对于同一个客户端程序,底层的服务端理论上是可以直接切换不同厂商的。
LDAP以树形结构存储数据,不支持事务,读性能远大于写性能。整棵树的任何一个分支都可以单独放在一个服务器中进行分布式管理,不仅有利于做服务器的负载均衡,还方便了跨地域的服务器部署。这个优势在查询负载大或企业在不同地域都设有分公司的时候体现尤为明显。
LDAP目录中存储了用户名和密码信息,使用LDAP登录的时候其实和普通的数据库登录没什么大的区别,客户端连接服务端后,搜索比对存储的用户名和密码信息。
springboot集成ldap:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-ldap</artifactId>
</dependency>
十一、SCIM
SCIM (System for Cross-domain Identity Management)跨域身份管理,主要用于多租户的云应用身份管理。
SCIM 是一种用户和组管理的新兴标准,通常用于替代传统 LDAP 协议。 SCIM 提供了 HTTP REST、跨企业和云应用程序部署所需的灵活性。 由于许多云服务不会提供 LDAP 接口,因此您可以使用与底层协议不同的 SCIM。
SCIM: System for Cross-domain Identity Managementhttp://www.simplecloud.info/SCIM 2.0建立在一个对象模型上,所有SCIM对象都继承Resource,它有id,externalId和meta属性,RFC7643定义了扩展公共属性的User,Group和EnterpriseUser。
对资源的操作,SCIM提供了一套REST API,包含丰富但简单的操作集,支持从修改特定用户的特定属性到进行批量更新的所有内容。
- Create: POST https://example.com/{v}/{resource}
- Read: GET https://example.com/{v}/{resource}/{id}
- Replace: PUT https://example.com/{v}/{resource}/{id}
- Delete: DELETE https://example.com/{v}/{resource}/{id}
- Update: PATCH https://example.com/{v}/{resource}/{id}
- Search: GET https://example.com/{v}/{resource}?filter={attribute}{op}{value}&sortBy={attributeName}&sortOrder={ascending|descending}
- Bulk: POST https://example.com/{v}/Bulk
十二、IAM
IAM(Identity and Access Management 的缩写),身份识别与访问管理(又称4A)。具有单点登录、强大的认证管理、基于策略的集中式授权和审计、动态授权、企业可管理性等功能。
4A是指:认证Authentication、授权Authorization、账号Account、审计Audit,中文名称为统一安全管理平台解决方案。即将身份认证、授权、记账和审计定义为网络安全的四大组成部分,从而确立了身份认证在整个网络安全系统中的地位与作用。
十三、IDaaS
IDaaS的全称是Identify as a Service,身份即服务,是一种构架在云上的身份服务。IDaaS是云化的身份和访问管理(IAM),IDaaS=SaaS+IAM。
阿里的:
什么是IDaaS,IDaaS有哪些功能_应用身份服务-阿里云帮助中心
https://help.aliyun.com/document_detail/112323.html
腾讯的:
账号连接器_千帆中台_企业身份管理- 腾讯云
结束语
普普通通的登录认证,随着软件系统的演进变得越来越复杂。但我们畅想着有一天,这种百花齐放的场景开始归一,会有一个超级系统,如始皇帝般横扫六合一统天下。畅想着有这么一种可能:国家队入场建立中央认证中心,将用户的身份认证前置到入网阶段,所有网上的系统都接入中央认证中心,所有网上系统都实现单点登录。