具体实现:
第三步:在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);