业务方视角,接入登录账号体系

前言:

上一篇我们介绍过了如何使用php+jwt。讲述如何制作一个一站式登录平台。打通各个业务方之间的账号壁垒。那么现在我就来介绍下。从业务方的角度,如何去接入一个登录中心

流程

业务方视角,接入登录账号体系_第1张图片
用户访问业务方地址
接入登录中心

首先我介绍下域名:

  • 登录中心的url是:tp.login.com:81
  • 接入方的域名是:tp.admin.com:81
    两个完全不一样的域名,也不存在session共享什么的。那么,现在我要把我的tp.admin.com:81接入到tp.login.com:81的账号体系中去。
    一:设计回调地址的路由
    由于我这次写的一个demo。就是直接在index模块下login控制器里写了个callback方法。如果在生产环境下的话还是推荐强制路由。这样url看上去美观点。好那么我们回调地址就是tp.admin.com:81/index.php/index/login/callback(这里有个细节,这个回调的地址,是不需要做登录验证的,因为刚回调回来的时候,cookie中还没有密文。所以这个控制器不继承有登录验证的那个控制器
    二:申请应用
    好了,既然都是我写的demo。就不存在申请不申请了。不过正规的流程应该是接入方会向登录中心的管理员,申请。告知回调地址。登录中心的管理员在app中添加回调地址,随机字符串作为秘钥,并获得appid。
    三:开始开发
    首先呢,我们将登录中心的地址,和分配给我们的appid 和app_key存到配置文件中方便使用
    业务方视角,接入登录账号体系_第2张图片
    配置文件

随后,我们既然是接入别人的登录中心,那就不用自己写登录了。直接写登录验证。
登录验证一般来说都会是写到一个控制器基类的__construct()方法里面

class Base extends Controller
{
    public $uid;
    public $name;

    public function __construct()
    {
        /**
         * 1.判断是否有cookie
         * 2.没有cookie,拼接回调地址和appid
         * 3.如果有cookie,解密code。验签
         * 4.延签失败删除cookie
         * 5.验签成功,初始化uid,name
         */
        try{
            $request=request();
            $authCode= cookie('authCode');
            if (empty($authCode)) {
                //拼接回调地址和appid
                $appid=config('sso.appid');
                //获取当前请求地址
                $callback_url=$request->url(true);
                //去配置文件中获取登录中心地址
                $login_url=config('sso.login_url');
                //拼接跳转地址
                $url=$login_url."?appid={$appid}&callback_url=".urlencode($callback_url);
                $this->redirect($url);
            }else{
                //如果有cookie
                //解密验签并取得cookie中的uid
                $uid=Auth::getUidByJwt($authCode);
                $this->uid=$uid;
            }
        }catch (Exception $e){
            $this->error($e->getMessage());
        }
    }
}

重点看看验签获取uid的方法。其实这个方法是一个基础方法扩展而成的。直接来看代码

    /**
     * 从jwt中获取某个字段
     * @param $token
     * @param $key
     * @return bool
     * @throws Exception
     */
    public static function getDataByJwt($token, $key)
    {
        //将token字符串初始化 token对象
        $tokenObj = (new Parser())->parse((string)$token);
        //实例化加密对象
        $signer = new Sha256();
        //使用配置中的秘钥验签
        $result = $tokenObj->verify($signer, config('sso.app_key'));
        if (!$result) {
            //验签失败
            //删除cookie,避免无限重定向
            cookie('authCode');
            throw new Exception('验签失败');
        }
        //使用检查过期时间的方法判断登录是否过期
        if ($tokenObj->isExpired()) {
            cookie('authCode');
            throw new Exception('登录过期');
        }
        //获取想要的数据
        $data = $tokenObj->getClaim($key);
        if ($data) {
            return $data;
        } else {
            return false;
        }
    }

    /**
     * 使用基础方法,获取uid
     * @param $token
     * @return bool
     * @throws Exception
     */
    public static function getUidByJwt($token)
    {
        return self::getDataByJwt($token, 'uid');
    }

其实jwt的包提供了非常丰富的方法,基本对密文没有太多的处理,验签之类的方法都准备好了。使用成本相当的低


上面介绍了验证登录的构造函数,还有一个地方别忘了。那就是我们最开始申请应用的那个回调地址。那个方法需要负责以下几个动作

  1. 获取登录中心传递过来的参数
  2. 验证code签名
  3. 将code写入cookie
  4. 从定向到用户最初访问的地址

下面来看代码

class Login extends Controller
{

    public function callback($code,$redirect)
    {
        try{
            //验签并取出uid
            $uid= Auth::getUidByJwt($code);
            //uid存在且回调地址存在
            if($uid&&$redirect){
                //写入cookie
                cookie('authCode',$code);
                //重定向到用户最初访问的地址
                $this->redirect($redirect);
            }else{
                //避免重定向
                cookie('authCode');
                $this->error('登录过期');
            }
        }catch (Exception $e){
            //避免重定向
            cookie('authCode');
            $this->error('登录过期');
        }

    }
}

当这一次重定向到用户访问的页面时,又会触发登录验证。这个时候,我们已经写好了cookie。cookie也是合法的。就会成功的取出用户的uid。下次用户访问这个应用的别的方法时,也携带这个cookie就可以正常使用了。更方便的是,我们在登录中心这个域名下还保存了一份cookie,当去访问别的应用时,别人的应用认为你没有登录重定向到登录中心后,就会检测到有cookie值并带上值重定向回别的应用。实现免登录

下面简单展示下效果


业务方视角,接入登录账号体系_第3张图片
l浏览器进入我们写的tp.admin这个应用

检测没有登录,重定向到登录中心


登录中心

随后输入密码账号,点击登录


业务方视角,接入登录账号体系_第4张图片
点击登录

然后又经历了两次重定向
一次是重定向到注册的回调地址,带上code
一次是写好cookie之后就重定向到最初访问的地址,我们从浏览器上也观察出回到了我们最初输入的那个地址


业务方视角,接入登录账号体系_第5张图片
回到最初访问的地址

并且我在首页输出了用户的id 1 这是通过解密jwt得到的uid

现在我们在刷新一下页面、由于已经有cookie保存了。所以不会再做重定向了。


业务方视角,接入登录账号体系_第6张图片
登录后再访问首页

我们还可以试试把tp.admin.com这个域名下的cookie删除,然后在访问首页。看会发生什么


业务方视角,接入登录账号体系_第7张图片
删除cookie

我们刷新下tp.admin.com 的主页


业务方视角,接入登录账号体系_第8张图片
又是一波疯狂的重定向

我们一步一步分析

  1. 重定向到了登录中心
  2. 登录中心发现有cookie存在就重定向到回调地址,带上cookie和redirect
  3. 回调地址,验签通过,初始化uid 并且重定向到最初访问的地址,也就是首页
    虽然做了几次重定向,但是对于用户来说是察觉不出来的。他体验到的是不需要登录的方便与快捷

好了今天的介绍接入登录中心就写到这里了。虽然还有些不完善的地方,不过这个机制是非常值得学习和可靠的。如果有不对的地方,望大神指正。感谢!

以上

你可能感兴趣的:(业务方视角,接入登录账号体系)