需求
多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?
涉及到的关键点:
这里就涉及到了 跨域认证 以及 前端页面 JavaScript 跨域 问题。
一、跨域认证问题
互联网服务离不开用户认证。一般流程是下面这样。
- 用户向服务器发送账户和密码
- 服务器验证通过后,在当前会话 (session)里保存相关数据,如用户角色、用户ID等
- 服务器向用户返回一个 session_id,写入用户 cookie
- 用户之后的每一次请求,都会通过 Cookie 将 session_id 传回服务器
- 服务器收到 session_id ,找到之前存储的数据,由此得知用户身份
下面以 登录 A 站点 访问 B 站点 为例
方案一: session 持久化
将 session 数据持久化,写入数据库或别的持久层。各种服务受到请求后,都向持久层请求数据。
这种方案,对于各种系统的代码改动量少,只要在权限验证的地方进行判断即可。
- A 登录成功代码
- 登录成功后,将 session 存储到 Redis 持久化存储,注意设置有效期
- tip:
Redis 以层级形式、目录形式保存数据,最大四级,格式如下:
set('dir:dir:dir:key', 'value');
/**
* 将 Session 存储到 Redis
* @param boolean $logout 是否退出登陆 默认否
* @return array
*/
public function sessionToRedis($logout = false) {
try {
if ($logout) {
(new Redis())->del('Admin:session:' . session_id());
}else{
$userInfo = session('CH_ADMIN_LOGIN_STATUS');
$res = (new Redis())->setex('Admin:session:' . session_id(), 28800, json_encode($userInfo, JSON_UNESCAPED_UNICODE));
if ($res === false) throw new \Exception('Redis 存储失败');
return tr