SSO单点登陆,单点注销设计思想

5、设计思路及折衷

        在常见的web站点中,当存在多个站点需要登陆,而这些站点都是使用同一套的登陆流程,

当用户在其中一个站点登陆后,其他站点并未记录用户的登陆信息,导致用户每次登陆新

站点需要进行新的登陆过程,这样给用户的体验是十分的不友好的,这时候就可以使用单点登陆,

单点注销的方式实现用户的登陆流程。

       由于站点是使用session存储用户信息的,所以该设计模式是针对session存储用户信息的设计方式,

首先以上系统1,系统2,sso认证中心都可以当作不同的站点,但是是使用同一套用户体系。为了实现单点

登陆,需要一个站点记录各个站点状态,就是sso认证中心。这存在唯一的登陆入口,就是sso认证中心提供

的登陆地址。当用户访问系统1时,如果系统1判断用户已经登陆,那么直接访问系统1站点内的资源,如果用户未登录

则请求到sso认证中心,判断认证中心,用户是否登陆。

 

一:如果认证中心记录用户已经登陆,则将登陆后的用户信息通过,jwt加密成token,转发给系统1,系统1在通过认证中心判断token是否有效,如果token正确,系统解析token后,将用户信息存储到session,其中token通过存储到cookie,配置不同子域同cookie,这样不同的站点只要*域名相同也可以获取同一个cookie。

二:如果认证中心记录用户未登陆,则跳转到sso的登陆入口。

三:以上过程需要将系统1的访问地址作为参数,在跳转过程作为参数传递,登陆成功后直接跳转到系统1地址。

四:当每次在sso认证中心认证token过程中,需要记录下所有系统的地址,然后在对这些地址进行注销,实现单点注销

但是本文章中的系统采用的是session作为存储信息,如果要清除session需要带上每一个系统的cookie,然后通过这些cookie

请求每个系统的注销接口。而记录这些cookie和路由地址到sso认证中心的缓存中,当访问的用户多的话,每一个用户都记录一份系统路由,cookie,对服务器压力可能也会比较大,于是换个角度想想,可以将其中一个站点点击注销后,将一个标记变量记录到cookie,访问其他站点如果发现这个cookie标记,则清除session,如果这个cookie标记在登陆过程中存在,则清除否则就会一直不能登陆。这样的话只需要每一个用户的浏览器记录cookie,就减轻服务器压力。

 

性能:比较单点注销的话,对服务器压力比较小。

可扩展性:该sso系统封装和配置好了对应内容,可以在各个模块下扩展开发。

安全性:可能cookie会被篡改,导致单点登陆失效。

服务稳定性:服务器不需要存储过多数据,也不会影响服务器性能。

6.1、模块流程图及说明

SSO单点登陆,单点注销设计思想

SSO单点登陆,单点注销设计思想

单点登录和单点注销的大致流程图如上。

实现单点登录的方式:

1. 在访问需要登录的站点A时,改站点A用户未登录,则请求到认证中心(参数:url=需要登录的站点A地址),判断用户在认证中心是否登录。

(1)如果用户在认证中心已登录,将用户信息使用jwt加密成token,发送至用户需要登录的站点A,也就是传过来的参数url站点,当然需要判断url是否合法,如http://www.baidu.com 这样的其他站点或者随机字符串等需要过滤。需要登录的站点A拿到token后(token的传输可以使用GET 或者 COOKIE(拿到token后需要清除token)),将token发送至认证中心,认证是否合法,如果token是合法的话,将token解析成用户信息,存储到站点A的SESSION中。这样站点A就属于登录状态,其他站点同理。

(2)如果用户在认证中心未登录,则跳转到认证中心的用户登录路口,并且这个路口后携带参数URL为站点A的地址。当用户登录成功后,则将token发送至站点A,站点A拿到token后(token的传输可以使用GET 或者 COOKIE(拿到token后需要清除token)),将token发送至认证中心,认证是否合法,如果token是合法的话,将token解析成用户信息,存储到站点A的SESSION中。这样站点A就属于登录状态,其他站点同理。

实现单点注销的方式:

(1)在其中一个站点A注销后,COOKIE记录一个标记。当其他站点访问需要登录的页面,发现到这个标记则注销。如果是登录情况下,发现这个标记则清理,这样就解决了单点注销的问题。

6.2、数据结构及说明

1.单点登录

//判断用户是否登录 否则请求sso认证中心 zhw20190327   单点登录
    public function check_login_sso(){
        $this->gethelper('http');
        $url  ="http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        //判断是否进行单点注销
        $login_out =$this->input->cookie("x7sy_login_out");
        if($login_out){
            $this->session->sess_destroy();
            locationUrl(Sso_Route."?url=$url",array());
        }
        //获取token 和当前请求地址的路由
        $token =$this->input->cookie("x7sy_token");
        $this->input->set_cookie("token",NULL,3600,Domain_Sub);
        //zhw 20190326 判断是否传递令牌
        if(!$this->isadminlogin()&& $token){
            //todo 校验令牌
            $res = sendCurlPost(Sso_Center."?url=$url",array("token"=>$token));
            //令牌正确记录用户信息到session
            if($res){
                $user_info = Jwt_tools::login_token_decode($token);
                $this->set_admin_session($user_info);
            }
            //跳转到登录页
            else{
                locationUrl(Sso_Center."?url=$url",array());
            }
        }
        //zhw 20190326 判断是否登录
        if(!$this->isadminlogin()){
            locationUrl(Sso_Center."?url=$url",array());
        }
    }
    

2.单点注销

    //20190402 zhw 单点注销
    public function loginout(){
        try{
            $this->admin_operation_log(1638,4,0,"管理员退出");
        }catch (Exception $e){}
        //todo 删除session
        $this->session->sess_destroy();
        $this->input->set_cookie("login_out",md5("flag"),3600,Domain_Sub);
        $this->adminMsg("退出成功,正在跳转!","ok",UrlRecombination("login/index",array(),$this->AdminFolder));
    }
    

3.认证中心

//zhw 20190326 sso认证中心
    public function check_login_center(){
        //访问需要登录页面的资源的地址
        $url =  $this->method_get_value("url");
        !$url &&  locationUrl(Sso_Route,array());
        //如果未登录,跳转到登录页面,附带域名地址作为参数
        if(!$this->isadminlogin()){
            locationUrl(Sso_Route."?url=$url",array());
        }
        //如果已登录,就将用户token提供给需要登录的页面,对应页面再创建局部会话。
        else{
            $token = $this->session->userdata("token");
            if($token&&$url) {
                $this->input->set_cookie("token",$token,3600,Domain_Sub);
                locationUrl($url,array());
            }
        }
    }

4.token校验

  //zhw 20190326 token验证是否有效
    public function check_login_token(){
        $token = $this->method_post_value("token");
        $url = $this->method_get_value("url");
        $user_info = Jwt_tools::login_token_decode($token);
        //获取到用户信息,如果用户信息正确,则说明token是有效的,过期的token是无效的
        if($user_info){
            //todo 将url存储起来 实现单点注销
            echo 1;
            exit();
        }
        echo 0;
        exit();
    }

以上是本次系统实现的单点登录,单点注销。

一:

其中还可以使用Redis Memcached 等方式记录SESSION,数据库用户表需要记录用户的SESSION_ID,通过SESSION_ID获取到SESSION 无论在哪个站点登录,都只需要使用同一套的SESSION,是很可观的,而且也支持跨域站点。COOKIE存在局限性

针对www.cc.xx www.xx.aa 这样的站点本次系统是不能实现单点登录,单点注销,但是使用Redis Memcached就可以。

二:

在本次系统上,如果单点注销是用过认证服务器带着每一个站点的SESSION_ID 访问退出登录的接口是可行的,但是服务器就需要存储每一个用户的所有站点SESSION_ID信息,然后每一个都发送注销请求,可能对服务器压力比较大。如有不足,请多多指教。萌新一枚