文章目录
- 一、单点登录系统的意义
- 1.1 提高用户体验
- 1.2 提高安全性
- 1.3 降低开发成本
- 1.4 提高操作效率
- 二、单点登录的实现方式
- 2.1 基于共享cookie的方式
- 2.2 基于代理服务器的方式
- 2.3 基于SAML协议的方式
- 2.4 基于OAuth协议的方式
- 三、用OAuth实现单点登录
- 3.1 OAuth 2.0 协议简介
- 3.2 OAuth 2.0协议授权流程
- 3.3 实现步骤
- 3.2.1 创建认证服务器
- 3.3.2 创建客户端应用
- 3.3.3 实现资源服务器
- 3.3.4 实现单点登录
- 3.4 代码实现
- 总结
一、单点登录系统的意义
单点登录系统的应用非常广泛,例如我们在阿里系的各种系统下面,如支付宝,淘宝、阿里云,登录了淘宝,再去阿里云控制台,无需二次登录。这就是典型的单点登录系统。
一般主流的有设计单点登录的平台,都有独立的单点登录域名和系统。比如下面是京东的登录页面。
单点登录之所以会被广泛使用,主要是有如下特点。
1.1 提高用户体验
用户可以更快速、方便地访问多个应用程序,不用频繁登录和输入多个帐号密码。
1.2 提高安全性
通过统一身份认证和授权,可以避免用户使用弱密码或重复密码,降低帐号被盗的风险。同时,SSO还可以实现集中管理用户权限、认证请求及安全策略,提高整体系统的安全性。
1.3 降低开发成本
采用SSO,可以降低多个应用程序的开发成本,减少维护工作量。
1.4 提高操作效率
对于企业内部的员工,SSO可以缩减操作步骤、简化工作流程,提高工作效率。
二、单点登录的实现方式
单点登录(Single Sign-On,简称SSO)是一种用户只需登录一次,就可以访问多个应用系统的身份认证技术。目前主流被经过验证的一些方式如下。
2.1 基于共享cookie的方式
将用户登录信息存储在一个共享cookie中,在用户跳转到不同的应用系统时,可以直接从共享cookie中获取用户的登录信息。
2.2 基于代理服务器的方式
在应用系统和用户之间增加一个代理服务器,当用户登录后,代理服务器会为用户生成一个令牌,用户访问其他应用系统时,需要携带该令牌,代理服务器会验证令牌的有效性,从而实现单点登录。
2.3 基于SAML协议的方式
SAML是一种基于XML的标准,用于安全地交换身份验证和授权数据。在该方式中,用户在登录时会被重定向到身份提供者,完成身份认证后,身份提供者会向服务提供者发送SAML断言,服务提供者通过断言验证用户身份,从而实现单点登录。
2.4 基于OAuth协议的方式
OAuth是一种授权框架,用于允许第三方应用程序访问用户资源。在该方式中,用户在登录时会被重定向到身份提供者,完成身份认证后,身份提供者会向应用程序颁发一个访问令牌,用户在访问其他应用程序时,需要携带该令牌,从而实现单点登录。
三、用OAuth实现单点登录
OAuth是使用最普遍的单点登录解决方案,下面就主要就这种登录方式进行讲解。
3.1 OAuth 2.0 协议简介
OAuth是一个授权协议,由雅虎和谷歌公司等组织提出并得到了很多互联网公司的支持和广泛应用。OAuth允许用户授权第三方应用访问他们存储在另外服务提供者上的信息,这样用户就不需要向第三方应用公开自己的密码等私人信息。
OAuth 2.0 是OAuth最新的版本,它被设计成适用于移动设备和云计算环境,并且易于实现。OAuth 2.0 授权流程的参与者包括用户(端点用户)、客户端应用程序(第三方应用程序)、资源所有者(受保护的资源的用户)和授权服务器。
OAuth实现单点登录主要分为以下几个步骤:
- 用户在资源服务器的网站上登录。也就是说,用户在某个网站里输入用户名和密码,资源服务器验证后,生成一个Authorization Code。
- 用户点击了想访问的服务端应用,然后浏览器将用户重定向到认证服务器,并把Authorization Code传递给了认证服务器。
- 认证服务器根据Authorization Code生成access token,并返回给浏览器。
- 浏览器携带access token跳转到服务端应用,然后服务端应用根据access token获取用户的信息,完成单点登录。
下面是OAuth 2.0授权流程的通用流程图:
3.2 OAuth 2.0协议授权流程
OAuth 2.0 协议授权流程包括以下步骤:
- 用户打开客户端应用
- 客户端应用向认证服务器请求授权
- 用户同意授权
- 认证服务器生成access token并返回给客户端应用
- 客户端应用携带access token访问资源服务器
- 资源服务器返回相应的资源
3.3 实现步骤
3.2.1 创建认证服务器
首先需要创建一个OAuth认证服务器,来完成用户登录及Token的颁发。可以使用现成的第三方OAuth认证服务器或者自己搭建。本文使用thephpleague/oauth2-server
来搭建OAuth认证服务器。
composer require league/oauth2-server
创建OAuth认证服务器,需要实现以下接口:
- ClientCredentialsGrantInterface:客户端凭证授权模式
- ImplicitGrantInterface:隐式授权模式
- ResourceOwnerPasswordCredentialsGrantInterface:密码授权模式
- RefreshTokenGrantInterface:刷新令牌授权模式
- AccessTokenInterface:AccessToken数据处理
- AuthorizationServerInterface:OAuth认证服务器
- ResourceServerInterface:OAuth资源服务器
在创建OAuth认证服务器时,需要将这些接口都实现,才能完成OAuth认证服务器的创建。
3.3.2 创建客户端应用
在OAuth认证服务器与资源服务器之间,需要通过客户端应用来实现单点登录流程中的授权与认证。客户端应用需要和OAuth认证服务器进行注册,并且需要得到授权服务器颁发给它的client id与secret,用于后续的授权流程。
实现OAuth 2.0客户端应用的步骤:
- 认证服务器创建客户端
- 客户端应用获取认证服务器颁发的client_id和client_secret
- 客户端应用通过client_id和client_secret向认证服务器请求access token和refresh token
3.3.3 实现资源服务器
在OAuth协议中,资源服务器需要具备以下几个功能:
- 接收客户端请求并检验access token的有效性
- 返回对应的用户资源
- 刷新access token
因此,需要在资源服务器上实现相应的接口,来满足以上几个功能。
实现OAuth 2.0资源服务器的步骤:
- 资源服务器通过client_id和client_secret向认证服务器请求access token
- 资源服务器获取到access token后,通过access token向认证服务器请求用户信息
- 认证服务器返回用户信息给资源服务器
- 资源服务器接收到认证服务器返回的用户信息之后,进行相应的业务操作
- 资源服务器刷新access token
3.3.4 实现单点登录
在单点登录流程中,应用程序需要进行如下处理:
- 从认证服务器获取access token
- 使用access token在资源服务器上进行验证
- 如果access token无效,从认证服务器重新获取access token
- 重复步骤2
在PHP中,可以使用thephpleague/oauth2-client
来获取access token,然后通过access token来访问资源服务器。
composer require league/oauth2-client
在获取access token之后,需要将access token缓存起来,当下一次访问资源服务器时,如果access token还未过期,则可以直接使用,否则需重新从认证服务器获取access token。
3.4 代码实现
单点登录(SSO)是一种身份验证机制,允许用户使用一个集中的登录凭据来访问多个应用程序。OAuth2是一个广泛使用的授权框架,可以用于实现单点登录。
以下是使用PHP oauth2-client库实现单点登录的步骤:
- 创建一个OAuth2客户端实例:
$provider = new League\OAuth2\Client\Provider\GenericProvider([
'clientId' => '{clientId}',
'clientSecret' => '{clientSecret}',
'redirectUri' => '{redirectUri}',
'urlAuthorize' => '{urlAuthorize}',
'urlAccessToken' => '{urlAccessToken}',
'urlResourceOwnerDetails' => '{urlResourceOwnerDetails}'
]);
在这里,我们需要提供OAuth2客户端的参数,包括clientId、clientSecret、redirectUri等。
- 在客户端应用程序中创建一个登录链接:
$authorizationUrl = $provider->getAuthorizationUrl();
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authorizationUrl);
exit;
这将重定向用户到OAuth2提供者的授权页面,要求用户提供其凭据以进行身份验证。
- 处理授权回调:
if (isset($_GET['code']) && isset($_GET['state']) && isset($_SESSION['oauth2state'])) {
if ($_SESSION['oauth2state'] !== $_GET['state']) {
exit('Invalid state');
}
try {
$accessToken = $provider->getAccessToken('authorization_code', [
'code' => $_GET['code']
]);
// Use this to interact with an API on the users behalf
echo $accessToken->getToken();
} catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {
exit('Failed to get access token');
}
} else {
exit('Invalid callback request');
}
在回调中,我们需要检查state参数以防止CSRF攻击。然后,我们使用提供者返回的授权代码获取访问令牌。一旦我们有了访问令牌,我们可以在用户的名义下与API进行交互。
- 在受保护的应用程序中使用访问令牌进行身份验证:
$accessToken = new League\OAuth2\Client\Token\AccessToken([
'access_token' => '{access_token}'
]);
// Make a call to the API using the access token
$result = $provider->getHttpClient()->get('{api_endpoint}', [
'headers' => [
'Authorization' => 'Bearer ' . $accessToken->getToken()
]
]);
在这里,我们使用访问令牌进行身份验证,在请求中添加“Authorization”头并将访问令牌作为Bearer标记发送。
总结
以上就是今天讲解的内容,单点登录设计方案介绍及用OAuth完整实现一个单点登录系统。本文从单点登录有哪些实现方案出发分析,到用OAuth方式是如何实现一个单点登录的这一套流程进行了一个完整的讲述。有疑问欢迎评论或者私信。感谢大家。