第三方应用与CRMEB标准版的用户整合及单点登录SSO实现《3》

具体实现:

第三步:在CRMEB内部系统中拦截URL地址中的授权凭据,并内部进行用户注册、基础资料同步;

  分步1:新建用户单点登录中间件(UserSSOMiddleware),文件路径:\app\http\middleware\UserSSOMiddleware.php;

//用户单点登录中间件:UserSSOMiddleware
class UserSSOMiddleware implements MiddlewareInterface
{
    private $ticket;
    private $access_token = '';
    private $expire_at = 0;
    private $refresh_token = '';
    private $refresh_expire_at = 0;

    private $app_id = '12*****1438';   //此处配置项为步骤一中生成
    private $app_key = 'y9Mc*****3Kxje';//此处配置项为步骤一中生成
    private $app_secret = 'kkhM*****9N2BP8';//此处配置项为步骤一中生成

    /**
     * @param Request $request
     * @param \Closure $next
     * @return Response
     */
    public function handle(Request $request, \Closure $next)
    {
        list($this->ticket) = $request->getMore([
            ['ticket','']
        ],true);

        if ($this->ticket !='') {
            //远程接口:获取访问授权
            $res = HttpService::request('https://api.xxxx.com/gateway.php?s=Gateway.OAuth.GetAccessToken', 'post', [
                'app_id' => $this->app_id,
                'app_key' => $this->app_key,
                'app_secret' => $this->app_secret,
                'timestamp' => msectime(),
                'ticket' => $this->ticket
            ]);
            $res_arr = $res ? json_decode($res, true) : [];

            if(!empty($res_arr) && $res_arr['ret'] == 200 && $res_arr['data']["is_success"] == true){
                $access_info = $res_arr['data']["info"];
                $this->access_token = $access_info['access_token'];
                $this->expire_at = $access_info['expire_at'];
                $this->refresh_token = $access_info['refresh_token'];
                $this->refresh_expire_at = $access_info['refresh_expire_at'];

                //使用当前授权同步并登录
                $user_info = $this->get_remote_user();
                if(!empty($user_info)){
                    $user = array(
                        'account'=>key_exists('user_name',$user_info) ? $user_info['user_name'] : '',
                        'nickname'=>key_exists('nick_name',$user_info) ? $user_info['nick_name'] : '',
                        'avatar'=>key_exists('user_avatar',$user_info) ? $user_info['user_avatar'] : '',
                        'sex'=>key_exists('user_sex',$user_info) ? $user_info['user_sex'] : '',
                        'phone'=>key_exists('user_mobile',$user_info) ? $user_info['user_mobile'] : '',
                        //'real_name'=>key_exists('real_name',$user_info) ? $user_info['real_name'] : '',
                        //'app_id'=>key_exists('app_id',$user_info) ? $user_info['app_id'] : '',
                        'mark'=>key_exists('uuid',$user_info) ? $user_info['uuid'] : '',
                    );
                    $user['account'] = empty($user['account']) ? $user['phone'] : $user['account'];
                    $user['nickname'] = empty($user['nickname']) ? $user['account'] : $user['nickname'];
                    if(!empty($user['account'])  && !empty($user['phone']) && !empty($user['mark'])){
                        //调用系统注册机登录过程
                        /** @var UserSyncForAppServices $userSyncForAppServices */
                        $userSyncForAppServices = app()->make(UserSyncForAppServices::class);
                        $userSyncForAppServices->syncUser($user);
                    }else{
                        Log::error('远程获取用户信息不完整');
                    }
                }else{
                    Log::info('远程获取用户信息为空');
                }

            }else{
                Log::error('远程获取授权出错:' . $res);
            }

        }
        return $next($request);
    }

    /**
     * 获取远程用户基本资料
     * @desc 根据授权远程获取用户当前资料
     * @return array 用户基本资料
     */
    private function get_remote_user(){
        $user_info = array();
        //远程接口:获取用户基本信息
        $res = HttpService::request('https://api.xxxx.com/gateway.php?s=Gateway.User.GetUserInfo', 'post', [
            'access_token' => $this->access_token,
            'ticket' => $this->ticket
        ]);
        $res_arr = $res ? json_decode($res, true) : [];

        if(!empty($res_arr) && $res_arr['ret'] == 200){
            $user_info = $res_arr['data'];
        }else{
            Log::error('远程获取用户资料出错:' . $res);
        }
        return $user_info;
    }
}


  分步2:新建用户单点登录核心服务(UserSyncForAppServices),文件路径:\app\services\user\UserSyncForAppServices.php;

***用户单点登录核心服务:UserSyncForAppServices***

//同步用户
public function syncUser($user)){
  ......
  //crmeb内部方法:根据用户全局唯一票据ticket获取用户基本信息
  $userInfo = $this->dao->getOne(['mark' => $user['mark'], 'is_del' => 0]);  //此处使用crmeb原有的字段mark来存储用户全局唯一票据ticket;
  if($userInfo) {
     self::updateUserInfo($user, $userInfo['uid']); //如果当前用户已存在:调用自定义方法更新用户资料
  } else {
      if ($userInfo = $this->dao->getOne(['account|phone' => $user['phone'], 'is_del' => 0])) {
           //因CRMEB内部是以用户名及手机号来区分账号的,因此判断当前手机号是否已被占用,
          //如手机号已存在,则调用自定义方法来绑定用户
           self::updateUserInfo($user, $userInfo['uid']);
     }else{
           self::register($user['mark'],'123456',$user, 'application');//如果当前用户不存在:调用自定义方法注册新用户
     }
  }
  ......
}

//更新用户基本信息
private function updateUserInfo($user,$uid){
  ......
  //此处略写:调用crmeb方法更新用户基本资料
  $data = array();
  $data['account'] = $user['account'];
  $data['phone'] = $user['phone'];
  $data['mark'] = $user['mark'];
  ......
  $is_update =$this->dao->update($uid, $data, 'uid');
  ......
}


//注册新用户
private function register($mark,$password = '123456',$user = array(),$user_type = 'application'){
  ......
  此处略写:调用crmeb方法注册新的用户信息
  $data = array();
  $data['mark'] = $mark;
  $data['pwd'] = md5((string)$password);
  $data['account'] = $user['account'];
  $data['phone'] = $user['phone'];
  ......
  $re = $this->dao->save($data);
  ......
}

  分步3:修改crmeb路由(中间件埋点:埋点后可在指定API的路由后面自动调用:用户单点登录中间件:UserSSOMiddleware),文件路径:\app\api\route\v1.php,大约389行;

    Route::get('get_lang_json', 'v1.PublicController/getLangJson')->name('getLangJson');
})->middleware(\app\http\middleware\AllowOriginMiddleware::class)->middleware(\app\api\middleware\StationOpenMiddleware::class)->middleware(\app\api\middleware\AuthTokenMiddleware::class, false);

修改为:

    Route::get('get_lang_json', 'v1.PublicController/getLangJson')->name('getLangJson');
})->middleware(\app\http\middleware\AllowOriginMiddleware::class)->middleware(\app\api\middleware\StationOpenMiddleware::class)->middleware(\app\api\middleware\AuthTokenMiddleware::class, false)->middleware(\app\http\middleware\UserSSOMiddleware::class);

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容