本篇文章根据个人理解的知识整理汇总, 如有不足之处, 请大家多多指正.
单点登录 (SSO--Single Sign On) 的应用是很普遍的, 尤其在大型网站系统中, 比如百度, 登录百度账号和, 再转到百度经验, 百度贴吧等是不用重新登录的. 本文将从 cookie 和 session 基础详细介绍单点登录的原理, 代码实现为 PHP.
Cookie
Cookie 是由客户端访问服务器时服务器发送给客户端的特殊信息, 且这些信息以文本文件的方式存储在客户端. 第一次访问服务器时, 服务器会在 HTTP 响应头 (Response Header) 返回 Cookie 信息. 客户端保存 Cookie 信息之后, 下次访问服务器时, HTTP 请求头 (Request Header) 会包含 Cookie 信息.
简单的说: 服务器不认识访问它的客户端, 为了识别它们, 就给每个访问它的客户端一个口令, 服务器通过口令识别这些客户端.
注意: 不是访问每个服务器都会返回 Cookie 的, 只有服务器中有设置 Cookie , 才会返回给客户端.
Cookie 生成和传递流程
在本地服务器下的 test.php 中设置 Cookie
- <?php
- // Cookie 是 HTTP 标头的一部分, 因此 setcookie() 函数必须在其它信息被输出到浏览器前调用, 这和对 header() 函数的限制类似
- setcookie('testCookie', 'this is test cookie');
通过浏览器访问本地服务器 localhost/test.php, 报文如下:
删除本地服务器下 test.php 中的 setcookie, 再次访问 localhost/test.php, 报文如下:
Cookie 流程图
简单登录示例:
- <?php
- # 登录
- setcookie('userName', 'test');
- # 判断是否已登录
- if (isset($_COOKIE['userName'])) {
- echo '已登录';
- }
关于 Cookie 的具体用法暂时不多说明, 本篇文章主要讲解机制原理
Session
Session 是服务器端使用的一种记录客户端状态的机制, 使用上比 Cookie 简单一些, 相应的也增加了服务器的存储压力. 在客户端访问服务器时, 服务器会创建 Session 并生成一个 Session id 发到客户端, 客户端下次访问时需要带着 Session id, 服务器则根据 Session id 找到相应的 Session.
Session 生成和传递流程
服务器设置 Session:localhost/session.php
- <?php
- session_start();
- $_SESSION['testSession'] = 'This is test';
客户端浏览器访问服务器: localhost/session.php, 报文如下图:
客户端浏览器再此访问服务器(注释代码):localhost/session.php, 报文如下:
Cookie 和 Session 的关系图(接上节中的设置)
单点登录
在介绍单点登录的方式之前先介绍一下 PHP 中的 Cookie 中的设置, 方便容易理解
bool setcookie ( string $name [, string $value = ""[, int $expire = 0 [, string $path ="" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] )
参数:
name: Cookie 名称.
value: Cookie 值.
expire: Cookie 的过期时间.
path: Cookie 有效的服务器路径. 设置成 '/' 时, Cookie 对整个域名 domain 有效. 如果设置成 '/foo/', Cookie 仅仅对 domain 中 /foo/ 目录及其子目录有效(比如 /foo/bar/). 默认值是设置 Cookie 时的当前目录.
domain: Cookie 的有效域名 / 子域名. 设置成子域名(例如'www.example.com'), 会使 Cookie 对这个子域名和它的三级域名有效(例如 w2.www.example.com). 要让 Cookie 对整个域名有效(包括它的全部子域名), 只要设置成域名就可以了(这个例子里是'example.com').
由上节我们知道, Session 是存放在服务器中的, 客户端与服务器的通信会话是通过 Session id 识别的, 客户端 Session id 是存放在 cookie 中, 因此单点登录大致分为: 同域名不同站点登录, 同域不同子域登录, 不同域名登录.
同域名不同站点登录
由 PHP 中的 Cookie 设置说明可以看出, 默认下不同站点是共享 Cookie 的除非设置了不同的有效服务器路径. 如果设置了不同的有效的服务器路径怎么实现共享登录呢? 哈哈哈, 那就将有效服务器路径设置为默认 '/' 的就好了.
同域不同子域登录
同样, 由 PHP 中的 Cookie 设置说明可以看出, 只要设置 Cookie 的 domain(Cookie 的有效域名 / 子域名) 参数就可以了, 如下:
由于 PHP 中生成 Session 会自动配置 Cookie, 因此我们可以直接在 Session 中设置 Cookie 有效域
- one.sso.test/create_session
- <?php
- session_set_cookie_params(time()+3600, '/', 'sso.test');
- session_start();
- $_SESSION['test'] = 'This is test';
- two.sso.test/get_session
- <?php
- session_set_cookie_params(time()+3600, '/', 'sso.test');
- session_start();
- echo $_SESSION['test'];
其中后者是可以获取到 Session 值的. 下边两图分别问以上两个子域名的报文和 Cookie 信息
图一:
图二:
由图可见他们的 Session id 是相同的, 因此调用的是服务器上的同一个 Session.
注意: 在 PHP 中, 配置 Session 的 Cookie 信息, 还可以通过修改 php.ini 文件设置
- session.cookie_path = /
- session.cookie_domain = '.sso.test'
- session.cookie_lifetime = 0
不同域名登录
由于涉及到用户信息安全问题, 因此本文通过流程图大致说一下基本 liu 流程, 具体操作看实际应用
注意: 上图中的 "返回 Cookie 信息" 并不是单独返回的, 而是在 "跳转页面" 的 HTTP 响应头 (Response Header) 返回, 同样异步请求的也是在 JS 调用 www.sso2.com 时在 HTTP 响应头 Response Header 返回.
本文到此结束, 后续如果有新的理解会补充上去.
来源: https://www.cnblogs.com/it-abel/p/9612143.html