>  기사  >  백엔드 개발  >  PHP Single Sign-On SSO 구현 방법

PHP Single Sign-On SSO 구현 방법

小云云
小云云원래의
2018-03-21 14:50:0312481검색

SSO는 서로 관련되어 있지만 독립적인 여러 시스템을 제어하기 위한 일종의 액세스 권한입니다. 이 권한이 있는 사용자는 서로 다른 사용자 이름이나 비밀번호를 사용하지 않고 하나의 ID와 비밀번호를 사용하여 하나 이상의 시스템에 액세스할 수 있습니다. 또는 일부 구성을 통해 각 시스템에 원활하게 로그인할 수 있습니다.

대규모 시스템의 경우 Single Sign-On을 사용하면 사용자의 많은 문제를 줄일 수 있습니다. Baidu를 예로 들면 Baidu Experience, Baidu Knows, Baidu Library 등 많은 하위 시스템이 있습니다. 이러한 시스템을 사용하는 경우 각 시스템에서 로그인하려면 사용자 이름과 비밀번호를 입력해야 합니다. 경험치가 확실히 떨어지겠죠.

SSO와 상호작용하는 두 가지 요소: 1. 사용자, 2. 시스템, 특성은 다음과 같습니다. 한 번의 로그인, 모든 액세스. SSO는 사용자의 로그인 가능 여부, 즉 사용자의 신원을 확인하는 일종의 접근통제이며, 그 외 모든 시스템 인증은 여기서 이루어진다. SSO를 전체 시스템 수준에서 보면 그 핵심은 다음 3가지이다. . 사용자, 2. 시스템, 3. 인증 센터.

PHP Single Sign-On SSO 구현 방법

1. 동일한 도메인이지만 다른 하위 도메인에 대해 Single Sign-On을 수행하는 방법

우리 사이트가 다음 도메인 이름에 따라 배포되었다고 가정합니다:
sub1.onmpw.com
sub2.onmpw.com

이것은 두 사이트 모두 mpw.com에서 동일한 도메인을 공유합니다.

기본적으로 브라우저는 쿠키가 속한 도메인에 해당하는 호스트로 쿠키를 보냅니다. 즉, sub1.onmpw.com의 쿠키에 대한 기본 도메인은 .sub1.onmpw.com입니다. 따라서 sub2.onmpw.com은 sub1.onmpw.com에 속한 쿠키 정보를 가져오지 않습니다. 서로 다른 호스트에 있고 하위 도메인도 다르기 때문입니다.

1.1 두 쿠키 정보를 동일한 도메인으로 설정

  • sub1.onmpw.com 시스템에 로그인

  • 로그인에 성공한 후 고유 식별자 토큰을 생성합니다. (토큰을 알면 어떤 사용자인지 알 수 있습니다. 로그인되어 있습니다.) 쿠키 정보 설정 여기서 주의할 점은 토큰은 쿠키에 저장되지만, 설정 시에는 이 쿠키가 속한 도메인을 최상위 도메인인 .onmpw.com으로 설정해야 합니다. 여기에서 setcookie 함수를 사용할 수 있습니다. 이 함수의 네 번째 매개변수는 쿠키의 도메인을 설정하는 데 사용됩니다.

setcookie(‘token’, ’xxx’, '/', ’.onmpw.com’);
  • sub2.onmpw.com 시스템을 방문하면 브라우저가 요청과 함께 쿠키에 포함된 정보 토큰을 sub2.onmpw.com 시스템으로 보냅니다. 이때 시스템은 먼저 세션이 로그인되어 있는지 확인합니다. 로그인되어 있지 않은 경우 쿠키의 토큰을 확인하여 자동 로그인을 수행합니다.

  • sub2.onmpw.com 로그인 성공 후 세션 정보를 작성합니다. 향후 확인을 위해 자신의 세션 정보를 사용하여 확인하세요.

1.2 로그아웃

여기서 문제는 sub1 시스템이 로그아웃한 후 자체 세션 정보와 .onmpw.com 도메인의 쿠키 정보를 지울 수 있다는 것입니다. sub2 시스템의 세션 정보는 삭제되지 않습니다. 해당 sub2는 아직 로그인되어 있습니다. 즉, 이 방법은 싱글 사인온을 달성할 수 있지만 동시 로그아웃을 달성할 수는 없습니다. 그 이유는 sub1과 sub2가 setcookie 함수의 설정을 통해 쿠키를 공유할 수는 있지만 sessionId가 다르고 이 sessionId도 브라우저에 쿠키 형태로 저장되지만 그것이 속한 도메인이 .onmpw가 아니기 때문입니다. .

이 문제를 해결하는 방법은 무엇입니까? 이 경우 두 시스템의 sessionId가 동일하면 이 문제가 해결될 수 있다는 것을 알고 있습니다. 즉, sessionId가 저장되어 있는 쿠키가 속한 도메인도 .onmpw.com입니다. PHP에서는 session_start()가 호출된 후에 sessionId가 생성됩니다. sub1과 sub2가 공통 sessionId를 가지도록 하려면 session_start() 이전에 sessionId가 속한 도메인을 설정해야 합니다.

ini_set('session.cookie_path', '/');
ini_set('session.cookie_domain', '.onmpw.com');
ini_set('session.cookie_lifetime', '0');

1 위 단계를 통해 서로 다른 초의 싱글 로그인 및 로그아웃을 달성할 수 있습니다. -레벨 도메인 이름.
2. 그러나 더 단순화할 수 있습니다. 예를 들어 sessionId가 동일하면 다른 2차 도메인 이름에 대한 싱글 로그인 및 로그아웃이 가능합니다.
참고 기사: https://www.onmpw.com/tm/xwzj/network_145.html

2. 서로 다른 도메인 간에 Single Sign-On을 구현하는 방법

다음 사이트 간에 Single Sign-On을 구현해야 한다고 가정해 보겠습니다.

www.onmpw1.com
www.onmpw2.com
www.onmpw3.com

위 해결 방법은 작동하지 않습니다.

현재 github에는 오픈 소스 SSO 솔루션이 있습니다. 구현 원칙은 주류 SSO와 유사합니다:
https://github.com/jasny/sso
wiki
demo

핵심 원칙:
1. 서로 다른 하위 시스템 시스템 및 하위 시스템에 해당하는 SSO 사용자 서비스 센터는 동일한 SessionId를 사용합니다. 2.
하위 시스템 브로커와 서버는 연결을 통해 인증 링크에 바인딩됩니다

同根域名不指定 domain 根域名,第一次授权需要每次都要跳转到授权服务,但是指定了domain, 同根域名只要有一个授权成功,都可以共用那个 cookie 了,下次就不用再授权了,直接就可以请求用户信息了。

第一次访问A:
PHP Single Sign-On SSO 구현 방법

第二次访问B:
PHP Single Sign-On SSO 구현 방법

2.1 登录状态判断

用户到认证中心登录后,用户和认证中心之间建立起了会话,我们把这个会话称为全局会话。当用户后续访问系统应用时,我们不可能每次应用请求都到认证中心去判定是否登录,这样效率非常低下,这也是单Web应用不需要考虑的。

我们可以在系统应用和用户浏览器之间建立起局部会话,局部会话保持了客户端与该系统应用的登录状态,局部会话依附于全局会话存在,全局会话消失,局部会话必须消失。

用户访问应用时,首先判断局部会话是否存在,如存在,即认为是登录状态,无需再到认证中心去判断。如不存在,就重定向到认证中心判断全局会话是否存在,如存在,通知该应用,该应用与客户端就建立起它们之间局部会话,下次请求该应用,就不去认证中心验证了。

2.2 退出

用户在一个系统退出了,访问其它子系统,也应该是退出状态。要想做到这一点,应用除结束本地局部会话外,还应该通知认证中心该用户退出。

认证中心接到退出通知,即可结束全局会话,用户访问其它应用时,都显示已登出状态。

需不需要立即通知所有已建立局部会话的子系统,将它们的局部会话销毁,可根据实际项目来。

SSO( Single Sign On ),即单点登录,是一种控制多个相关但彼此独立的系统的访问权限, 拥有这一权限的用户可以使用单一的ID和密码访问某个或多个系统从而避免使用不同的用户名或密码,或者通过某种配置无缝地登录每个系统 。

对于大型系统来说使用单点登录可以减少用户很多的麻烦。就拿百度来说吧,百度下面有很多的子系统——百度经验、百度知道、百度文库等等,如果我们使用这些系统的时候,每一个系统都需要我们输入用户名和密码登录一次的话,我相信用户体验肯定会直线下降。

与 SSO 交互的2个元素:1.  用户,2. 系统,它的特点是:一次登录,全部访问。SSO 是访问控制的一种,控制用户能否登录,即验证用户身份,而且是所有其它系统的身份验证都在它这里进行,从整个系统层面来看 SSO ,它的核心就是这3个元素了:1. 用户,2. 系统,3. 验证中心。

PHP Single Sign-On SSO 구현 방법

1、同一个域但不同的子域如何进行单点登录

假如我们的站点是按照下面的域名进行部署的:
sub1.onmpw.com
sub2.onmpw.com

这两个站点共享同一域 onmpw.com 。

默认情况下,浏览器会发送 cookie 所属的域对应的主机。也就是说,来自于 sub1.onmpw.com 的 cookie 默认所属的域是 .sub1.onmpw.com 。因此,sub2.onmpw.com 不会得到任何的属于 sub1.onmpw.com 的 cookie 信息。因为它们是在不同的主机上面,并且二者的子域也是不同的。

1.1 设置二者的 cookie 信息在同一个域下

  • 登录 sub1.onmpw.com 系统

  • 登录成功以后,生成唯一标识符Token(知道token,就知道哪个用户登录了)。设置 cookie 信息,这里需要注意,将Token存到 cookie 中,但是在设置的时候必须将这 cookie 的所属域设置为顶级域 .onmpw.com 。这里可以使用 setcookie 函数,该函数的第四个参数是用来设置 cookie 所述域的。

setcookie(‘token’, ’xxx’, '/', ’.onmpw.com’);
  • 访问 sub2.onmpw.com 系统,浏览器会将 cookie 中的信息 token 附带在请求中一块儿发送到 sub2.onmpw.com 系统。这时该系统会先检查 session 是否登录,如果没有登录则验证 cookie 中的 token 从而实现自动登录。

  • sub2.onmpw.com 登录成功以后再写 session 信息。以后的验证就用自己的 session 信息验证就可以了。

1.2 退出登录

这里存在一个问题就是 sub1 系统退出以后,除了可以清除自身的 session 信息和所属域为 .onmpw.com 的 cookie 的信息。它并不能清除 sub2 系统的 session 信息。那 sub2 仍然是登录状态。也就是说,这种方式虽说可以实现单点登录,但是不能实现同时退出。原因是,sub1 和 sub2 虽说通过 setcookie 函数的设置可以共享 cookie,但是二者的sessionId 是不同的,而且这个 sessionId 在浏览器中也是以 cookie 的形式存储的,不过它所属的域并不是 .onmpw.com 。

那如何解决这个问题呢?我们知道,对于这种情况,只要是两个系统的 sessionId 相同就可以解决这个问题了。也就是说存放 sessionId 的 cookie 所属的域也是 .onmpw.com 。在PHP中,sessionId 是在 session_start() 调用以后生成的。要想使sub1 和 sub2 有共同的 sessionId ,那必须在 session_start() 之前设置 sessionId 所属域:

ini_set('session.cookie_path', '/');
ini_set('session.cookie_domain', '.onmpw.com');
ini_set('session.cookie_lifetime', '0');

1、经过上面的步骤就可以实现不同二级域名的单点登录与退出。
  2、不过还可以再简化,如确保 sessionId 相同就可以实现不同二级域名的单点登录与退出。
 参考文章: https://www.onmpw.com/tm/xwzj/network_145.html

2、不同域之间如何实现单点登录

假设我们需要在以下这些站之间实现单点登录

www.onmpw1.com
www.onmpw2.com
www.onmpw3.com

上面的方案就行不通了。

目前 github 上有开源的 SSO 解决方案,实现原理与主流 SSO 差不多:
https://github.com/jasny/sso
wiki
demo

核心原理:  
1、客户端访问不同的子系统,子系统对应的 SSO 用户服务中心使用相同的 SessionId
2、子系统 Broker 与 Server 间通过 attach 进行了授权链接绑定

同根域名不指定 domain 根域名,第一次授权需要每次都要跳转到授权服务,但是指定了domain, 同根域名只要有一个授权成功,都可以共用那个 cookie 了,下次就不用再授权了,直接就可以请求用户信息了。

第一次访问A:
PHP Single Sign-On SSO 구현 방법

第二次访问B:
PHP Single Sign-On SSO 구현 방법

2.1 登录状态判断

用户到认证中心登录后,用户和认证中心之间建立起了会话,我们把这个会话称为全局会话。当用户后续访问系统应用时,我们不可能每次应用请求都到认证中心去判定是否登录,这样效率非常低下,这也是单Web应用不需要考虑的。

我们可以在系统应用和用户浏览器之间建立起局部会话,局部会话保持了客户端与该系统应用的登录状态,局部会话依附于全局会话存在,全局会话消失,局部会话必须消失。

用户访问应用时,首先判断局部会话是否存在,如存在,即认为是登录状态,无需再到认证中心去判断。如不存在,就重定向到认证中心判断全局会话是否存在,如存在,通知该应用,该应用与客户端就建立起它们之间局部会话,下次请求该应用,就不去认证中心验证了。

2.2 退出

用户在一个系统退出了,访问其它子系统,也应该是退出状态。要想做到这一点,应用除结束本地局部会话外,还应该通知认证中心该用户退出。

认证中心接到退出通知,即可结束全局会话,用户访问其它应用时,都显示已登出状态。

需不需要立即通知所有已建立局部会话的子系统,将它们的局部会话销毁,可根据实际项目来。

相关推荐:

实例讲解SSO单点登录原理

单点登录原理和简单实现

php实现的SSO单点登录系统接入功能示例分析

위 내용은 PHP Single Sign-On SSO 구현 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.