• redis的详解和项目应用之SESSION共享


    前言:承接上文 redis的详解和项目应用之PHP操作总结

    三、项目应用 

    3.1 项目介绍

    此项目为了实现单点登录(Single Sign On),简称为 SSO,是比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    单点登录使用的是session共享技术,然而session是不能跨服务器的,但是将session存储在一台 redis/memcache 缓存服务器上就可以实现跨服务器session信息共享,实现过程如下图所示:

    过程说明:

    需要准备一台web服务器用来做一个授权登录系统,然后再准备几台其他站点的web服务器。实现是通过登录后的session信息存储到redis中,并且通过跳转将SESSIONID传递到相关的各个系统站点的cookie中来记录登录状态,通过cookie中的SESSIONID请求登录服务器来获取存储到redis中的用户信息,即实现单点登录。

    3.2 前期配置

    1、准备一台登录服务器,安装 redis-server,在ubuntu服务器执行

    apt install redis-server

    安装需要配置远程连接,建议可看我之前发布的文章 redis的详解和项目应用之数据类型_m0_68949064的博客-CSDN博客

    2、 将登录服务器和其他web服务器上的PHP都安装上 php-redis 扩展,在ubuntu服务器上执行

    1. # 依照个人的php版本进行安装redis扩展
    2. apt install php7.2-redis

     3、修改php.ini来配置将session存储到远程redis中

    1. # 修改php.ini文件中 [Session] 下的配置
    2. session.save_handler = redis
    3. session.save_path = "tcp://ip:6379?auth=YOURPASSPHRASE"

    3.3 实现结果

    代码:

    登录服务器的 config.php 文件

    1. /**
    2. * 配置文件,安装个人项目的配置来
    3. */
    4. //同步登录web域名数组
    5. $synUrlAll = [
    6. web1,
    7. web2,
    8. ];
    9. //认证中心的web域名
    10. $centerUrl = centerUrl;
    11. //私钥
    12. $privateKey = 'redisKey';
    13. //redis配置
    14. $redisConfig = [
    15. 'host' => centerUrl,
    16. 'port' => '6379',
    17. 'timeout' => '604800',
    18. 'auth_pass' => YOURPASSPHRASE,
    19. ];

    登录服务器的 center.php 文件

    1. header('Content-Type:application/json; charset=utf-8');
    2. error_reporting(E_ERROR | E_CORE_ERROR | E_PARSE);
    3. include_once "./config.php";
    4. /**
    5. * 登录认账中心
    6. */
    7. class center
    8. {
    9. protected $synUrlAll;
    10. protected $centerUrl;
    11. protected $privateKey;
    12. protected $redisConfig;
    13. function __construct($synUrlAll, $centerUrl, $privateKey, $redisConfig)
    14. {
    15. $this->synUrlAll = $synUrlAll;
    16. $this->centerUrl = $centerUrl;
    17. $this->privateKey = $privateKey;
    18. $this->redisConfig = $redisConfig;
    19. }
    20. public function toLogin()
    21. {
    22. $data = $_POST;
    23. if(!isset($data['username']) || !$data['username']){
    24. return $this->returnJosn(500, '缺少username参数');
    25. }
    26. if(!isset($data['passwd']) || !$data['passwd']){
    27. return $this->returnJosn(500, '缺少passwd参数');
    28. }
    29. // 此处登录验证省略,并假设用户ID为1
    30. $userInfo = [
    31. 'uid' => 1,
    32. 'username' => $data['username'],
    33. 'passwd' => $data['passwd'],
    34. ];
    35. $login_key = 'PHPREDIS_SESSION:'.session_id();
    36. $_SESSION['uid'] = 1;
    37. $_SESSION['userInfo'] = $userInfo;
    38. setcookie('login_key', $login_key, time()+3600*24, '/');
    39. return $this->synAllWeb($login_key);
    40. //return $this->returnJosn(200, '登录成功');
    41. }
    42. //同步登录
    43. public function synLogin()
    44. {
    45. $data = $_GET;
    46. if(!isset($data['login_key']) || !$data['login_key']){
    47. return $this->returnJosn(500, '缺少login_key参数');
    48. }
    49. $login_key = base64_decode($data['login_key']);
    50. $login_key = substr($login_key, 0, strlen($login_key)-strlen($this->privateKey));
    51. setcookie('login_key', $login_key, time()+3600*24, '/');
    52. header("Location:".base64_decode($data['returnUrl']).$data['urlAll']);
    53. exit;
    54. }
    55. //将登录的sessionid同步至其他网站
    56. public function synAllWeb($login_key = '')
    57. {
    58. if(!$login_key){
    59. $login_key = $_COOKIE['login_key'];
    60. }
    61. if(isset($_GET['urlAll'])){
    62. $urlAll = isset($_GET['urlAll']) ? trim(base64_decode($_GET['urlAll'])) : '';
    63. $urlAll = json_decode($urlAll, true);
    64. }else{
    65. $urlAll = $this->synUrlAll;
    66. }
    67. if(is_array($urlAll) && !empty($urlAll)){
    68. sort($urlAll);
    69. $url = $urlAll[0];
    70. unset($urlAll[0]);
    71. header("Location:http://".$url."/web.php?act=synLogin&login_key=".base64_encode($login_key.$this->privateKey)."&urlAll=".base64_encode(json_encode($urlAll))."&returnUrl=".base64_encode("http://".$this->centerUrl."/redisObj/center.php?act=synAllWeb&urlAll="));
    72. exit;
    73. }else{
    74. return $this->isLogin();
    75. }
    76. }
    77. public function isLogin()
    78. {
    79. if(isset($_COOKIE['login_key']) && $_COOKIE['login_key']){
    80. $redis = $this->redis();
    81. $session_str = stripslashes($redis->get($_COOKIE['login_key']));
    82. if($session_str){
    83. $index = strpos($session_str, ';');
    84. $str = substr($session_str, ($index+1));
    85. $userInfo = unserialize(str_replace('userInfo|', '', $str));
    86. return $this->returnJosn(200, '登录中', json_encode(['userInfo'=>$userInfo]));
    87. }else{
    88. unset($_COOKIE['login_key']);
    89. return $this->returnJosn(500, '登录失效');
    90. }
    91. }else{
    92. return $this->returnJosn(500, '登录失效');
    93. }
    94. }
    95. public function loginOut()
    96. {
    97. unset($_COOKIE['login_key']);
    98. unset($_SESSION['uid']);
    99. unset($_SESSION['userInfo']);
    100. session_destroy();
    101. return $this->returnJosn(200, '已退出登录');
    102. }
    103. protected function redis()
    104. {
    105. $redisConfig = $this->redisConfig;
    106. $redis = new Redis();
    107. $redis->pconnect($redisConfig['host'], $redisConfig['port'], $redisConfig['timeout']);
    108. $redis->auth($redisConfig['auth_pass']);
    109. return $redis;
    110. }
    111. protected function returnJosn($code, $msg = '', $data = array())
    112. {
    113. echo json_encode([$code, $msg, $data], JSON_UNESCAPED_UNICODE);
    114. exit;
    115. }
    116. }
    117. session_start();
    118. $act = isset($_GET['act']) ? trim($_GET['act']) : 'isLogin';
    119. if($act){
    120. $center = new center($synUrlAll, $centerUrl, $privateKey, $redisConfig);
    121. $center->$act();
    122. }

    登录服务器的 login.html 文件(统一登录页面)

    1. html>
    2. <html>
    3. <head>
    4. <title>登录页面title>
    5. head>
    6. <body>
    7. <meta charset="utf-8">
    8. <h3>登录页面h3>
    9. <form action="./center.php?act=toLogin" method="post">
    10. <input type="text" name="username" value="username11"><br/>
    11. <input type="password" name="passwd" value="pwd11"><br/>
    12. <input type="submit" value="登录">
    13. form>
    14. body>
    15. html>

     其他web服务器的 web.php 文件

    1. header('Content-Type:application/json; charset=utf-8');
    2. error_reporting(E_ERROR | E_CORE_ERROR | E_PARSE);
    3. /**
    4. * 站点1,使用此方法登录依次其他站点
    5. */
    6. class web1
    7. {
    8. protected $privateKey;
    9. protected $redisConfig;
    10. function __construct($privateKey, $redisConfig)
    11. {
    12. $this->privateKey = $privateKey;
    13. $this->redisConfig = $redisConfig;
    14. }
    15. //同步登录
    16. public function synLogin()
    17. {
    18. $data = $_GET;
    19. if(!isset($data['login_key']) || !$data['login_key']){
    20. return $this->returnJosn(500, '缺少login_key参数');
    21. }
    22. $login_key = base64_decode($data['login_key']);
    23. $login_key = substr($login_key, 0, strlen($login_key)-strlen($this->privateKey));
    24. setcookie('login_key', $login_key, time()+3600*24, '/');
    25. header("Location:".base64_decode($data['returnUrl']).$data['urlAll']);
    26. exit;
    27. }
    28. public function isLogin()
    29. {
    30. if(isset($_COOKIE['login_key']) && $_COOKIE['login_key']){
    31. $redis = $this->redis();
    32. $session_str = stripslashes($redis->get($_COOKIE['login_key']));
    33. if($session_str){
    34. $index = strpos($session_str, ';');
    35. $str = substr($session_str, ($index+1));
    36. $userInfo = unserialize(str_replace('userInfo|', '', $str));
    37. return $this->returnJosn(200, '登录中', json_encode(['userInfo'=>$userInfo]));
    38. }else{
    39. unset($_COOKIE['login_key']);
    40. return $this->returnJosn(500, '登录失效');
    41. }
    42. }else{
    43. return $this->returnJosn(500, '登录失效');
    44. }
    45. }
    46. public function loginOut()
    47. {
    48. unset($_COOKIE['login_key']);
    49. return $this->returnJosn(200, '已退出登录');
    50. }
    51. protected function redis()
    52. {
    53. $redisConfig = $this->redisConfig;
    54. $redis = new Redis();
    55. $redis->pconnect($redisConfig['host'], $redisConfig['port'], $redisConfig['timeout']);
    56. $redis->auth($redisConfig['auth_pass']);
    57. return $redis;
    58. }
    59. protected function returnJosn($code, $msg = '', $data = array())
    60. {
    61. echo json_encode([$code, $msg, $data], JSON_UNESCAPED_UNICODE);
    62. exit;
    63. }
    64. }
    65. $act = isset($_GET['act']) ? trim($_GET['act']) : 'isLogin';
    66. //私钥
    67. $privateKey = 'redisKey';
    68. //redis配置
    69. $redisConfig = [
    70. 'host' => '106.12.155.232',
    71. 'port' => '6379',
    72. 'timeout' => '604800',
    73. 'auth_pass' => 'redispwd11',
    74. ];
    75. if($act){
    76. $web1 = new web1($privateKey, $redisConfig);
    77. $web1->$act();
    78. }
  • 相关阅读:
    利用 Pandoc + ChatGPT 优雅地润色论文,并保持 Word 公式格式:Pandoc将Word和LaTeX文件互相转化
    Python技能树练习——统计词频
    【办公自动化】在Excel中按条件筛选数据并存入新的表2.0(文末送书)
    gdb调试常见命令详细总结
    解析java中的除法运算和取模运算
    小白学爬虫:通过关键词搜索1688商品列表数据接口|1688商品列表数据接口|1688商品列表数据采集|1688API接口
    提升运营效率:仓储可视化的实时监控与优化
    RocketMQ-RocketMQ部署(Linux、docker)
    如何优雅的配置 Java 微服务
    Java版企业电子采购招标系统源码
  • 原文地址:https://blog.csdn.net/m0_68949064/article/details/126606439