接入集团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 \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    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 \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    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

后序

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

posted @ 2019-06-14 17:21  泥土里的绽放  阅读(461)  评论(0编辑  收藏  举报