zoukankan      html  css  js  c++  java
  • 接入集团auth流程

    前言

        一直对集团的auth系统很感兴趣,所以这次记录下接入集团auth的流程。如果后期有时间,会补充具体的auth实现细节。

    正文

    一、实现思想

    1. 实现思想

        明确几个名词:接入方,管理方。接入方指的是:要接入auth系统的这些应用;管理方指的是:管理应用程序的地方,也就是我们的auth系统。

        auth的大致的实现逻辑就是:需要进行权限验证的接入方的请求url在进行权限验证的时候把所有的验证、管理、授权操作都通过发送请求的方式来让管理方来处理。那么就可以理解为:用户有没有登录的权限,有没有某个请求的权限都是通过管理方来判断的。

        具体流程图如下所示:

    二、实现代码

    1. url请求需要经过中间件

    2. 请求中间件代码

    class Authenticate
    {
        public function handle(Request $request, Closure $next)
        {
            if (!Aus::checkLogin()) {
                return Aus::goLogin($request->url());
            }
    
            $uri = "/".trim($request->route()->uri, "/");
    
            if (!Aus::authorize($uri)) {
                $msg = '对不起,你没有对应的权限,请联系管理员!';
    
                if ($request->ajax()) {
                    $ajaxResp = json_encode(['code' => 401, 'message' => $msg], JSON_UNESCAPED_UNICODE);
                    return response($ajaxResp, 200);
                }
    
                return response("<h2>$msg</h2>", 401);
            }
    
            return $next($request);
        }
    }
    View Code
    class AuthenticateService
    {
        private static $notAuthList = ["/"];
    
        /**
         * 验证登陆
         *
         * @return bool
         */
        public static function checkLogin()
        {
            if (Config::get('auto_auth.ignore_auth', false)) {
                return true;
            }
            return Session::has('user') ? true : false;
        }
    
        /**
         * 鉴权
         * @param $uri
         * @return bool
         */
        public static function authorize($uri)
        {
            if (Config::get('auto_auth.ignore_auth', false)) {
                return true;
            }
    
            // 不用校验的URI
            if (in_array($uri, self::$notAuthList)) {
                return true;
            }
    
            if (!Session::has('user.permissions')) {
                return false;
            }
            if (!Session::has('user.token')) {
                return false;
            }
    
            $user = Session::get('user');
    
            foreach ($user['permissions'] as $permission) {
                $permission = rtrim($permission, '/');
                if ($permission) {
                    $permission = '#'.$permission.'#';
                    if (@preg_match($permission, $uri)) {
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        /**
         * 通过Auth系统登陆
         *
         * @param string $token
         *
         * @return array|bool
         */
        public static function getUserByToken($token)
        {
            $ssoCheckUrl = Config::get('auto_auth.url') . '/sso/checktoken?token=' . $token;
            $httpResponse = file_get_contents($ssoCheckUrl);
            $content = [];
    
            if ($httpResponse) {
                $content = json_decode($httpResponse, true);
            }
            if (isset($content['code']) && 0 == $content['code']) {
                $allPermissions = array_get($content, 'data.permissions', []);
                $permissions = [];
                $baseRole = null;
                foreach ($allPermissions as $permission) {
                    if ($permission['app_key'] == Config::get('auto_auth.app_key')) {
                        $permissions[] = $permission['regex'];
                    }
                }
    
                $userInfo = [
                    'user_id' => $content['data']['account'],
                    'username' => $content['data']['name'],
                    'email' => $content['data']['email'],
                    'mobile' => $content['data']['mobile'],
                    'ttl' => $content['data']['ttl'],
                    'token' => $token,
                    'permissions' => $permissions,
                    'baseRule' => !is_null($baseRole) ?? 0,
                ];
                session(['user' => $userInfo]);
    
                return $userInfo;
            }
    
            return false;
        }
    
        /**
         * 跳转登陆页面
         * @param $targetUrl
         * @return IlluminateHttpRedirectResponse|IlluminateRoutingRedirector
         */
        public static function goLogin($targetUrl)
        {
            $params = [
                'tarurl' => $targetUrl,
                'app_key' => Config::get('auto_auth.app_key'),
            ];
    
            $params_str = http_build_query($params);
            $login_url = Config::get('auto_auth.url') . Config::get('auto_auth.api_list.login') . '?' . $params_str;
            return redirect($login_url);
        }
    
        /**
         * 登出
         * @param $targetUrl
         * @return IlluminateHttpRedirectResponse|IlluminateRoutingRedirector
         */
        public static function goLogout($targetUrl)
        {
            $params = [
                'tarurl' => $targetUrl,
                'app_key' => Config::get('auto_auth.app_key'),
                'token' => Session::get('user.token'),
            ];
    
            $params_str = http_build_query($params);
            $logout_url = Config::get('auto_auth.url') . Config::get('auto_auth.api_list.login') . '?' . $params_str;
            Session::forget('user');
    
            return redirect($logout_url);
        }
    
        // 获取当前登录用户信息
        public static function getAuthUser()
        {
            if (!self::checkLogin()) {
                return [];
            }
            return Session::get('user');
        }
    
        /**
         * 获取当前登录用户的ID
         */
        public static function getLoginUserId()
        {
            return array_get(Session::get('user'), 'user_id', 0);
        }
    
        /**
         * 获取当前登录用户的ID
         */
        public static function getLoginMobile()
        {
            return array_get(Session::get('user'), 'mobile', 0);
        }
    
        /**
         * 获取登陆用户的邮箱
         */
        public static function getLoginEmail()
        {
            return array_get(Session::get('user'), 'email', '');
        }
    
        /**
         * 获取当前登录用户的名字
         */
        public static function getLoginUserName()
        {
            return array_get(Session::get('user'), 'username', 'admin');
        }
    
        /**
         * 获取当前登录用户权限列表(正则表达式)
         * @return array
         */
        public static function getUserPermissions()
        {
            $user = self::getAuthUser();
            return array_get($user, 'permissions', []);
        }
    
        /**
         * 获取授权菜单
         * @param $list
         * @return mixed
         */
        public static function getAuthMenu($list) {
            if (Config::get('auto_auth.ignore_auth', false)) {
                return $list;
            }
    
            $result = [];
            $parentCount = [];
            foreach ($list as $item) {
                //父级菜单直接通过
                if ($item['pid'] == 0) {
                    $result[] = $item;
                } else {
                    //有权限的子菜单
                    if (self::authorize($item['auth_url'])) {
                        $result[] = $item;
                        //标记被使用到的父级菜单
                        $parentCount[$item['pid']] = 1;
                    }
                }
            }
    
            //去掉没有用过的父级菜单
            foreach ($result as $k => $item) {
                if ($item['pid'] == 0 && empty($parentCount[$item['id']])) {
                    unset($result[$k]);
                }
            }
    
            return $result;
        }
    }
    View Code
    Route::group(['prefix' => '/sso', 'namespace' => 'Auth'], function () {
        Route::get('/login', 'SsoController@login');
        Route::get('/jump', 'SsoController@jump');
        Route::get('/logout', 'SsoController@logout');
    
        if(env('APP_ENV', 'local') == 'local') {
            Route::get('/mockLogin', 'SsoController@mockLogin');
        }
    });
    View Code
    class SsoController extends Controller
    {
        /**
         * 登陆
         */
        public function login(Request $request)
        {
            $validator = Validator::make(
                $request->all(), [
                    'action' => 'required|in:login,logout',
                    'token' => 'required',
                ]
            );
    
            if ($validator->fails()) {
                return -1;
            }
    
            if ('login' != $request->get('action')) {
                return -2;
            }
            $token = $request->get('token');
    
            $user = Aus::getUserByToken($token);
    
            if (empty($user)) {
                return -2;
            }
    
            return response($request->callback . "('" . Config::get('auto_auth.app_key') . "')")
                ->withCookie('token', $request->token, 10000000)
                ->header('p3p', 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
        }
    
        public function logout(Request $request)
        {
            $url = $request->root();
            return Aus::goLogout($url);
        }
    
        public function jump() {
            return Aus::goLogin("http://".$_SERVER['HTTP_HOST']."/index/home");
        }
    
        public function mockLogin(Request $request) {
    
            $userInfo = [
                'user_id' => array_get($request, 'user_id'),
                'username' => array_get($request, 'username', ''),
                'email' => array_get($request, 'email', ''),
                'mobile' => array_get($request, 'mobile', ''),
                'ttl' => 3600*100,
            ];
            session(['user' => $userInfo]);
        }
    }
    View Code
    AUTO_AUTH_IGNORE_AUTH=false
    #AUTO_AUTH_URL=
    AUTO_AUTH_URL=
    AUTO_AUTH_APP_URL=
    AUTO_AUTH_APP_KEY=
    AUTO_AUTH_API_LIST_LOGIN=
    View Code

    3. 后台配置项目相关内容

    三、总结

        总的流程是:

        添加中间件代码 => 修改中间件涉及的代码 => 修改env配置 => 后端配置

        注意:测试环境可用dev4

    后序

        不积跬步无以至千里,不积小流无以成江海

  • 相关阅读:
    2020-05-28 Beta冲刺第一天
    团队作业第六次——凡事预则立
    团队作业第六次——alpha阶段问题总结随笔
    团队作业第五次——冲刺总结
    2020-05-08 冲刺第十天
    团队作业第五次——测试随笔
    软件工程实践2019第三次作业
    软件工程实践2019第二次作业
    软件工程实践2019第一次作业
    M4C:TextVQA的分布预测多模态Transformers
  • 原文地址:https://www.cnblogs.com/cjjjj/p/11024450.html
Copyright © 2011-2022 走看看