单点登录系统的应用非常广泛,例如我们在阿里系的各种系统下面,如支付宝,淘宝、阿里云,登录了淘宝,再去阿里云控制台,无需二次登录。这就是典型的单点登录系统。
一般主流的有设计单点登录的平台,都有独立的单点登录域名和系统。比如下面是京东的登录页面。
用户可以更快速、方便地访问多个应用程序,不用频繁登录和输入多个帐号密码。
通过统一身份认证和授权,可以避免用户使用弱密码或重复密码,降低帐号被盗的风险。同时,SSO还可以实现集中管理用户权限、认证请求及安全策略,提高整体系统的安全性。
采用SSO,可以降低多个应用程序的开发成本,减少维护工作量。
对于企业内部的员工,SSO可以缩减操作步骤、简化工作流程,提高工作效率。
单点登录(Single Sign-On,简称SSO)是一种用户只需登录一次,就可以访问多个应用系统的身份认证技术。目前主流被经过验证的一些方式如下。
将用户登录信息存储在一个共享cookie中,在用户跳转到不同的应用系统时,可以直接从共享cookie中获取用户的登录信息。
在应用系统和用户之间增加一个代理服务器,当用户登录后,代理服务器会为用户生成一个令牌,用户访问其他应用系统时,需要携带该令牌,代理服务器会验证令牌的有效性,从而实现单点登录。
SAML是一种基于XML的标准,用于安全地交换身份验证和授权数据。在该方式中,用户在登录时会被重定向到身份提供者,完成身份认证后,身份提供者会向服务提供者发送SAML断言,服务提供者通过断言验证用户身份,从而实现单点登录。
OAuth是一种授权框架,用于允许第三方应用程序访问用户资源。在该方式中,用户在登录时会被重定向到身份提供者,完成身份认证后,身份提供者会向应用程序颁发一个访问令牌,用户在访问其他应用程序时,需要携带该令牌,从而实现单点登录。
OAuth是使用最普遍的单点登录解决方案,下面就主要就这种登录方式进行讲解。
OAuth是一个授权协议,由雅虎和谷歌公司等组织提出并得到了很多互联网公司的支持和广泛应用。OAuth允许用户授权第三方应用访问他们存储在另外服务提供者上的信息,这样用户就不需要向第三方应用公开自己的密码等私人信息。
OAuth 2.0 是OAuth最新的版本,它被设计成适用于移动设备和云计算环境,并且易于实现。OAuth 2.0 授权流程的参与者包括用户(端点用户)、客户端应用程序(第三方应用程序)、资源所有者(受保护的资源的用户)和授权服务器。
OAuth实现单点登录主要分为以下几个步骤:
下面是OAuth 2.0授权流程的通用流程图:
OAuth 2.0 协议授权流程包括以下步骤:
首先需要创建一个OAuth认证服务器,来完成用户登录及Token的颁发。可以使用现成的第三方OAuth认证服务器或者自己搭建。本文使用thephpleague/oauth2-server
来搭建OAuth认证服务器。
composer require league/oauth2-server
创建OAuth认证服务器,需要实现以下接口:
在创建OAuth认证服务器时,需要将这些接口都实现,才能完成OAuth认证服务器的创建。
在OAuth认证服务器与资源服务器之间,需要通过客户端应用来实现单点登录流程中的授权与认证。客户端应用需要和OAuth认证服务器进行注册,并且需要得到授权服务器颁发给它的client id与secret,用于后续的授权流程。
实现OAuth 2.0客户端应用的步骤:
在OAuth协议中,资源服务器需要具备以下几个功能:
因此,需要在资源服务器上实现相应的接口,来满足以上几个功能。
实现OAuth 2.0资源服务器的步骤:
在单点登录流程中,应用程序需要进行如下处理:
在PHP中,可以使用thephpleague/oauth2-client
来获取access token,然后通过access token来访问资源服务器。
composer require league/oauth2-client
在获取access token之后,需要将access token缓存起来,当下一次访问资源服务器时,如果access token还未过期,则可以直接使用,否则需重新从认证服务器获取access token。
单点登录(SSO)是一种身份验证机制,允许用户使用一个集中的登录凭据来访问多个应用程序。OAuth2是一个广泛使用的授权框架,可以用于实现单点登录。
以下是使用PHP oauth2-client库实现单点登录的步骤:
$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方式是如何实现一个单点登录的这一套流程进行了一个完整的讲述。有疑问欢迎评论或者私信。感谢大家。