单点登录(SingleSignOn,SSO)
Keycloak
Keycloak 是一个身份和访问管理开源解决方案,它支持多种身份验证和授权协议,常用的包括 OpenID Connect (OIDC) 和 OAuth 2.0 协议。
-
OpenID 连接 (OIDC):
- 协议特点:建立于OAuth 2.0以上,用于身份验证。OIDC提供认证(Authentication)和授权(Authorization)功能,允许客户端应用程序验证用户身份,并获取有关用户的信息。
- 使用场景:适用于需要用户身份、获取用户信息并进行访问控制的场景,比如单点登录(SSO)、用户权限管理验证等。
- 使用方式:在 Java Spring Boot 框架中,你可以使用 Keycloak 的 Java Adapter,它为 Spring Security 提供了集成支持,使得在 Spring Boot 应用中使用 OIDC 非常简单。
-
OAuth 2.0协议:
- 协议:主要用于授权,允许第三方应用程序通过令牌来访问用户的资源,而不需要用户提供其权益(比如用户名和密码)给第三方应用。
- 使用场景:适用于需要授权访问资源的场景,如访问 API、委托授权等。Keycloak 也支持 OAuth 2.0 协议。
- 使用方式:在 Java Spring Boot 框架中,您可以使用 Keycloak 的 OAuth 2.0 Adapter,与 Spring Security 结合,以保护和授权您的应用程序的资源。
关于为什么选择使用 OIDC 和 OAuth 2.0 以及其应用场景:
-
OIDC 和 OAuth 2.0 的选择:
- OIDC和OAuth 2.0提供了标准化的身份验证和授权机制,使得应用程序能够安全地管理用户身份验证和授权访问资源。
- 使用这些协议可以简化身份验证和授权流程,并提供了许多安全性的特性,比如令牌化、认证机制等。
-
为什么选择Keycloak:
- Keycloak 提供了对这些协议的全面支持,并且易于集成到 Java Spring Boot 应用程序中。
- 它提供了身份验证、授权、用户管理等功能,并提供易于使用的管理界面和API。
-
OAuth 2.0 登录认证协议:
- 特点:OAuth 2.0 是一个授权框架,允许第三方应用程序通过访问令牌(A***ess Token)来获取受保护的资源,同时保护了用户的权益。
- 应用场景:用于委托授权、API访问控制等场景。它使得用户可以授权第三方应用程序代表其访问资源,而无需提供其资源。
- 使用方式:在应用程序中实现OAuth 2.0流程,包括授权请求、访问令牌获取等步骤。
OAuth 2.0
OAuth 2.0 是一个开放标准的授权协议,主要用于授权第三方应用程序访问受保护的资源,而不需要用户提供其权限(例如用户名和密码)。尤其在单点登录(SSO)和身份验证方面,OAuth 2.0 在一定的编程中支持这些功能,尽管它不是专门设计的。
以下是OAuth 2.0协议的关键概念和特点:
-
授权流程:
- 资源所有者:拥有受保护资源的用户。
- 客户端:希望访问第三方应用程序的资源。
- 授权服务器:负责认证用户并颁发访问令牌(A***ess Token)的服务器。
- 资源服务器:存储受保护的资源并根据访问令牌提供对这些资源的访问。
-
角色:
- 授权服务器:负责验证资源所有者的身份,并根据资源所有者的同意授予访问令牌给客户端。
- 资源服务器:存储受保护的资源,并根据访问令牌验证客户端对资源的访问权限。
-
授权类型:
- 授权码授权(Authorization Code Grant):用于Web应用程序,通过授权码交换访问令牌。
- 隐式授权(Implicit Grant):适用于浏览器或移动应用,直接从授权端点获取访问令牌。
- 密码授权(Resource Owner Password Credentials Grant):资源所有者提供用户名和密码直接交换访问令牌。
- 客户端授权授权(Client Credentials Grant):适用于机器对机器通信,客户端通过自身凭证获取访问令牌。
-
单点登录(SSO)和身份验证:
- OAuth 2.0并不是专门为单点登录设计的,但它提供了一些机制,使得可以在多个系统间进行认证并赋予更灵活的功能。
- 通过 OAuth 2.0,用户可以通过授权服务器一次性登录,并在授权内部使用访问令牌访问多个资源。
-
安全性:
- OAuth 2.0 使用令牌化的方式,访问令牌代表用户的访问权限,并不是直接暴露用户的权限(例如用户名和密码)。
- 有效管理和保护令牌是保证安全性的关键,包括令牌的时效性、访问范围、加密方式等。
用户登录流程
- 用户尝试访问客户端应用,但尚未认证。
- 客户端检测到用户未经认证,发起重定向至认证服务器请求认证。
- 用户被重定向至认证服务器,在此进行身份验证,并被询问授权请求。
- 用户授权成功后,认证服务器发回授权码至客户端。
- 客户端使用授权码交换访问令牌(A***ess Token)和刷新令牌(Refresh Token)。
- 客户端使用 A***ess Token 请求资源服务器获取用户资源。
- 资源服务器验证 A***ess Token,若合法则提供用户资源。
客户端/服务端交互
- 客户端: 负责重定向到认证服务器,并获取访问令牌用于访问资源服务器。
- 服务端: 包括认证服务器和资源服务器,认证服务器负责验证用户身份并颁发令牌,资源服务器验证令牌并提供资源。
虽然OAuth 2.0在一定程度上支持单点登录和验证,但它更关注授权身份和资源访问,而不是认证。为了实现更完整的单点登录体验,通常需要与其他身份验证协议(例如OpenID)连接)结合使用。
总的来说,OAuth 2.0是一种灵活的授权协议,适用于很多场景下的授权访问需求,但在考虑实现单点登录或完整的身份验证系统时,可能需要结合其他协议和技术来实现更多全面的解决方案。
OpenID Connect
OpenID Connect简称为OIDC,是一个以用户为中心的数字身份识别框架,是第三代OpenID技术,扩展了 OAuth 2.0 授权协议,在OAuth2.0上构建了身份层,使其可用作身份验证协议。 OIDC 通过一个称作“ID 令牌”的安全令牌在支持 OAuth 的应用程序之间启用单点登录 (SSO)。OpenID是一个去中心化的网上身份认证系统。对于支持OpenID的网站,用户不需要记住像用户名和密码这样的传统验证标记。取而代之的是,他们只需要预先在一个作为OpenID身份提供者(identity provider, IdP)的网站上注册。OpenID是去中心化的,任何网站都可以使用OpenID来作为用户登录的一种方式,任何网站也都可以作为OpenID身份提供者。OpenID既解决了问题而又不需要依赖于中心性的网站来确认数字身份。
OAuth2实际上只做了授权,而OpenID Connect在授权的基础上又加上了认证。
OIDC的优点是:简单的基于json的身份令牌(JWT),并且完全兼容OAuth2协议。
OpenID(认证)+OAuth 2.0(授权)=OpenID Connect(认证+授权)。
使用标准的JWT令牌,REST/JSON消息流,允许开发人员跨网站和应用程序验证其用户,而无需拥有和管理密码。OpenID Connect的设计支持web程序、本地应用程序和移动应用程序。
用户登录流程
- 用户请求访问客户端。
- 客户端重定向至认证服务器。
- 用户在认证服务器上进行身份验证和授权。
- 认证服务器发放 ID 令牌至客户端。
- 客户端使用 ID 令牌验证用户身份,并获取用户信息。
客户端/服务端/认证中心交互
- 客户端: 发起登录请求并验证 ID 令牌。
- 服务端: 可以是客户端应用或资源服务器,用于验证 ID 令牌。
- 认证中心: 负责用户身份验证并生成 ID 令牌。
OpenID的理念和CAS正好相反,CAS强调中心化,OpenID强调去中心化。OpenID协议提供了一个基本的认证机制。
OpenID身份提供者(identity provider, IdP):何人都可以建立一个网站提供OpenID验证服务
OpenID 客户端:就是集成了 OpenID 登录服务的应用系统。
应用系统可以是单一的身份提供者,也可以是单一的客户端,也可以既是提供者又是客户端。
OpenID的理念非常先进,他幻想着所有厂家之间都保持着足够的友好性、开放性和兼容性,大厂和小厂之间可以平等对话,大家共同构建一个无障碍的身份识别体系。你可以使用某一网站的帐号去登录另一网站,只要这些网站都是实现了OpenID的服务。这一理念对用户非常友好,但在现实世界却寸步难行,国内系统基本上看不到。
1、虽然人人都可以是身份提供者,但能够提供高质量、长期、稳定的服务必然是少数大厂。到最后所谓的去中心化,也还是会变成中心化。
2、哪个应用系统不想沉淀自己独有的用户群体呢?各厂家之间怎么可能会互相信任呢?支付宝、微信这种大佬系统上永远不会出现三方登录的入口。大家都在构建属于自己的帝国。
JWT (JSON Web Token)
JWT (全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
用户登录流程
- 用户登录时获取 JWT 包含声明信息。
- 客户端将 JWT 发送至服务端。
- 服务端验证 JWT 的签名和声明信息的完整性。
客户端/服务端交互
- 客户端: 用户使用账号、密码登录应用,登录的请求发送到 Authentication Server。
- 服务端: Authentication Server 进行用户验证,然后创建 JWT 字符串返回给客户端。
- 客户端: 客户端请求接口时,在请求头带上 JWT。
- **服务端:**Application Server 验证 JWT 合法性,如果合法则继续调用应用接口返回结果。
可以看出与token方式有一些不同的地方,就是不需要依赖 redis,用户信息存储在客户端。所以关键在于生成 JWT 和解析 JWT 这两个地方。
JWT的数据结构
JWT 一般是这样一个字符串,分为三个部分,以 “.” 隔开:
xxxxx.yyyyy.zzzzz
Header
JWT 第一部分是头部分,它是一个描述 JWT 元数据的 Json 对象,通常如下所示。
{
"alg": "HS256",
"typ": "JWT"
}
alg 属性表示签名使用的算法,默认为 HMAC SHA256(写为HS256),typ 属性表示令牌的类型,JWT 令牌统一写为JWT。
最后,使用 Base64 URL 算法将上述 JSON 对象转换为字符串保存。
Payload
JWT 第二部分是 Payload,也是一个 Json 对象,除了包含需要传递的数据,还有七个默认的字段供选择。
- iss (issuer):签发人/发行人
- sub (subject):主题
- aud (audience):用户
- exp (expiration time):过期时间
- nbf (Not Before):生效时间,在此之前是无效的
- iat (Issued At):签发时间
- jti (JWT ID):用于标识该 JWT
如果自定义字段,可以这样定义:
{
//默认字段
"sub":"主题123",
//自定义字段
"name":"java技术爱好者",
"isAdmin":"true",
"loginTime":"2021-12-05 12:00:03"
}
12345678
需要注意的是,默认情况下 JWT 是未加密的,任何人都可以解读其内容,因此一些敏感信息不要存放于此,以防信息泄露。
JSON 对象也使用 Base64 URL 算法转换为字符串后保存,是可以反向反编码回原样的,这也是为什么不要在 JWT 中放敏感数据的原因。
Signature
header (base64URL 加密后的)
payload (base64URL 加密后的)
secret
12345
JWT 第三部分是签名。是这样生成的,首先需要指定一个 secret,该 secret 仅仅保存在服务器中,保证不能让其他用户知道。这个部分需要 base64URL 加密后的 header 和 base64URL 加密后的 payload 使用 . 连接组成的字符串,然后通过header 中声明的加密算法 进行加盐secret组合加密,然后就得出一个签名哈希,也就是Signature,且无法反向解密。
那么 Application Server 如何进行验证呢?可以利用 JWT 前两段,用同一套哈希算法和同一个 secret 计算一个签名值,然后把计算出来的签名值和收到的 JWT 第三段比较,如果相同则认证通过。
JWT的优点
- json格式的通用性,所以JWT可以跨语言支持,比如Java、JavaScript、PHP、Node等等。
- 可以利用Payload存储一些非敏感的信息。
- 便于传输,JWT结构简单,字节占用小。
- 不需要在服务端保存会话信息,易于应用的扩展。
SAML (Security Assertion Markup Language)
安全断言标记语言(英语:Security Assertion Markup Language,简称SAML)是一个基于XML的开源标准数据格式,它在系统之间交换身份验证和授权数据,尤其是在身份提供者和服务提供者之间交换。SAML解决的最重要的需求是Web端应用的单点登录,目前能见到的基本都是最新版本 2.0 。
协议古老且内容庞大, 特点是使用xml传输,SP(Service Provider)和IDP(Identity Provider)之间不直接通讯,而是通过用户的浏览器进行两次重定向完成认证跳转。
用户登录流程
- 用户请求访问服务提供者资源。
- 服务提供者重定向至身份提供者(IdP)。
- 用户在 IdP 上进行身份验证,IdP 生成包含用户信息的 SAML 断言(Assertion)。
- 断言发送至服务提供者。
- 服务提供者验证断言,确认用户身份,并授权访问。
客户端/服务端/认证中心交互
- 客户端: 用户或服务提供者发起身份验证请求。
- 服务端: 服务提供者验证 SAML 断言。
- 认证中心: 负责用户身份验证并生成断言。
Kerberos
Kerberos协议 是一个专注于验证通信双方身份的网络协议,不同于其他网络安全协议的保证整个通信过程的传输安全,Kerberos侧重于通信前双方身份的认定工作,帮助客户端以及服务端验证是真正的自己并非他人,从而使得通信两端能够完全信任对方的身份,在一个不安全的网络中完成一次安全的身份认证继而进行安全的通信。
Kerberos协议中存在三个角色,分别是:
客户端(Client):发送请求的一方
服务端(Server):接收请求的一方
密钥分发中心(Key distribution KDC)
密钥分发中心又分为两个部分,分别是:
AS(Authentication Server):认证服务器,专门用来认证客户端的身份并发放客户用于访问TGS的TGT(票据授予票据)
TGS(Ticket Granting ticket):票据授予服务器,用来发放整个认证过程以及客户端访问服务端时所需的服务授予票据(ticket)
Kerberos认证过程简化描述如下:
客户端在访问每个想要访问的网络服务时,他需要携带一个专门用于访问该服务并且能够证明自己身份的票据,当服务端收到了该票据他才能认定客户端身份正确,向客户端提供服务。所以整个流程可简化为两大步:
(1)客户端向KDC请求获取想要访问的目标服务的服务授予票据(Ticket);
(2)客户端拿着从KDC获取的服务授予票据(Ticket)访问相应的网络服务;
用户登录流程
- 用户尝试访问服务并向 Key Distribution Center (KDC) 请求票证(Ticket)。
- KDC 发放票证至用户,票证包含用户信息和访问权限。
- 用户使用票证访问其他服务,无需再次提供凭据。
客户端/服务端/认证中心交互
- 客户端: 发起登录请求并获取票证。
- 服务端: 验证票证并授权用户访问。
- 认证中心: 负责用户身份验证和票证颁发。
CAS
CAS是Central Authentication Service的缩写,中央认证服务,一种独立开放指令协议。旨在为Web应用提供一种可靠的单点登录方法。CAS Server负责对用户的认证,而CAS Client负责提供资源,当资源受保护时需要用户进行身份认证时,重定向到CAS Server进行认证。
协议特点
1、开源的企业级单点登录解决方案。
2、CAS Server 为需要独立部署的 Web 应用。
3、CAS Client 支持非常多的客户端(这里指单点登录系统中的各个 Web 应用),包括 Java, .***, PHP, Perl, Apache, uPortal, Ruby 等语言编写的各种web应用。
4、CAS属于Apache 2.0许可证,允许代码修改,再发布(作为开源或商业软件)。
CAS服务器是基于Spring Framework构建的Java servlet,其主要职责是通过签发和验证票据来验证用户并授予对支持CAS的服务(CAS客户端程序)的访问权限。
CAS客户端是一个软件包,可以与各种软件平台和应用程序集成,以便通过某些身份验证协议(例如CAS、SAML、OAuth)与CAS服务器通信。
客户端通过几种受支持的协议中的任何一种与服务器通信。除了自己的CAS协议外,市面上主流的基本都支持,如SAML、OpenID Connect、OpenID、OAuth 2.0等。
用户登录认证流程
- 用户访问需要登录的应用系统,如果用户尚未登录,客户端会检测并提示用户进行登录。
- 客户端根据预先配置的CAS服务器信息,将用户重定向到CAS服务器的登录页面。
- 在登录页面上,用户输入用户名和密码,并提交给CAS服务器进行认证。
- CAS服务器进行用户认证,验证用户的身份信息。如果认证通过,CAS服务器将生成一个登录凭据(通常是一个加密的令牌),并将该凭据返回给客户端。
- 客户端验证登录凭据的有效性。如果凭据有效,客户端将会把用户重定向到最初访问的应用系统。
- 在应用系统中,客户端将会把登录凭据发送给应用系统进行验证。应用系统会向CAS服务器发送请求以验证该凭据的有效性。
- 如果凭据有效,应用系统将会允许用户访问其所需的资源。如果凭据无效或过期,用户将被要求重新进行登录。
客户端/服务端/认证中心交互
- 客户端:客户端负责与用户的交互,包括接收用户的登录请求,向CAS服务器发送认证请求,以及接收和处理CAS服务器的响应。客户端通常会使用HTTP重定向的方式将用户重定向到CAS服务器进行认证。在认证完成后,客户端将会保存登录凭据,并将其发送给应用系统以进行后续的访问控制。
- CAS服务器:CAS服务器是负责用户认证的核心组件。它接收来自客户端的认证请求,验证用户的身份信息,并生成加密的令牌作为登录凭据。CAS服务器将会把令牌返回给客户端,并记录相关信息以便后续的访问控制。
- 认证中心:认证中心是一个可选的组件,它负责管理用户的身份信息和授权信息。认证中心可以与CAS服务器集成,以提供更加强大的身份验证和授权功能。在登录过程中,认证中心可以向CAS服务器提供用户的身份信息,以便CAS服务器进行验证。同时,认证中心也可以根据用户的授权信息来控制用户对应用系统的访问权限。
总的来说,CAS协议通过客户端与服务端的交互实现了用户登录认证的功能。在认证过程中,使用了加密的令牌作为登录凭据,确保了用户身份的安全性和可信性。同时,通过与认证中心的集成,可以实现更加强大的身份验证和授权功能。
LDAP
轻型目录访问协议(英文:Lightweight Directory A***ess Protocol,缩写:LDAP)。是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式的目录信息。LDAP起源于上个世纪,延续至今在企业内部(OA、ERP)的地位依然牢不可破。一个常用用途是单点登录,用户可以在多个服务中使用同一个账密,常用于公司内部网站的登录认证。
简单地说:
1、DAP是一个协议(X.500),LDAP是他的一个轻量级变种协议
2、LDAP(轻型目录访问协议)是一种目录访问协议,而目录信息是存储在目录数据库内的。实现了LDAP协议的目录数据库有很多,其中最出名、影响最广的就是 Microsoft Active Directory。除此之外,还有Sun one Directory、IBM directory server。以及开源的openldap(OpenLDAP, Main Page)、Apache Directory LDAP(Wel***e to Apache Directory — Apache Directory)。
3、我们常说的LDAP服务器,是指部署了某一目录数据库(如微软的Active Directory)的应用服务器,该服务器对外提供LDAP服务。
4、目录数据以树形结构存储,不支持事务,读性能远大于写性能。
目录数据库由服务端和客户端组成,这一点和我们常用的关系型数据库(mysql)一样。但不同的是,LDAP数据库的客户端和服务端通讯是遵循标准的LDAP协议的,故对于同一个客户端程序,底层的服务端理论上是可以直接切换不同厂商的。
LDAP以树形结构存储数据,不支持事务,读性能远大于写性能。整棵树的任何一个分支都可以单独放在一个服务器中进行分布式管理,不仅有利于做服务器的负载均衡,还方便了跨地域的服务器部署。这个优势在查询负载大或企业在不同地域都设有分公司的时候体现尤为明显。
LDAP目录中存储了用户名和密码信息,使用LDAP登录的时候其实和普通的数据库登录没什么大的区别,客户端连接服务端后,搜索比对存储的用户名和密码信息。
用户登录认证流程
- 用户在客户端输入用户名和密码。
- 客户端根据预先配置的LDAP服务器信息,将用户名和密码发送到LDAP服务器进行认证。
- LDAP服务器在目录中查找用户信息,如果找到匹配的用户名和密码,则认证通过,否则认证失败。
- 如果认证通过,LDAP服务器返回一个成功的响应,否则返回一个错误码或错误消息。
- 客户端根据响应判断认证是否成功,如果成功,则用户可以访问应用系统,否则需要重新输入用户名和密码。
客户端/服务端/认证中心交互
- 客户端:客户端负责与用户的交互,包括接收用户的登录请求,向LDAP服务器发送认证请求,以及接收和处理LDAP服务器的响应。客户端可以是一个Web浏览器、桌面应用程序或移动应用程序等。在认证过程中,客户端需要将用户名和密码进行加密或摘要处理,以确保数据的安全性。
- LDAP服务器:LDAP服务器负责用户认证的核心组件。它接收来自客户端的认证请求,在目录中查找用户信息,如果找到匹配的用户名和密码,则认证通过,否则认证失败。LDAP服务器通常是一个独立的服务器或作为目录服务的一部分部署。在认证过程中,LDAP服务器需要对密码进行加密或摘要处理,以保护用户信息的安全性。
- 认证中心:认证中心是一个可选的组件,它负责管理用户的身份信息和授权信息。认证中心可以与LDAP服务器集成,以提供更加强大的身份验证和授权功能。在登录过程中,认证中心可以向LDAP服务器提供用户的身份信息,以便LDAP服务器进行验证。同时,认证中心也可以根据用户的授权信息来控制用户对应用系统的访问权限。
总的来说,LDAP协议通过客户端与服务端的交互实现了用户登录认证的功能。在认证过程中,使用了加密或摘要处理的方式保护用户信息和密码的安全性。同时,通过与认证中心的集成,可以实现更加强大的身份验证和授权功能。