第三方登陸的使用在當今很是廣泛,無論是PC端仍是手機端都很常見。由於它有着一號多用的特色,無論是在什麼網站什麼軟件上只要有了這個第三方登陸的功能就無需再次走註冊步驟,直接用第三方的帳號登陸就能夠了,方便吧?開發程序看重的是用戶體驗,爲用戶打造一款「麻雀雖小,五臟俱全」,使用便利的產品是咱們的職責。那麼話又說回來,在Restfual api 上如何實現第三方登陸呢?我在Segmentfault上找不到我想要的答案,不過最終我也實現了,我把個人實現思路寫出來,固然這只是個人一種實現方式,要是你們有更好的方法呢,樂意交流。php
一、用Restfual api的架構實現第三方登陸,如QQ,微信登陸等。api
一、建兩個表,user表和user_login表。user表我就不詳說了,這是基本表,我重點說一下user_login表。
user_login表字段:微信
id id user_id 用戶id type 登陸類型(如:QQ,weixin) qq_access_token QQ受權access_token qq_openid QQ openid wx_access_token 微信受權access_token wx_openid 微信openid
要是還有微博或者淘寶之類的其餘第三方登陸就如以上的規律加上對應的字段就好了。架構
二、gii生成UserLogin.php model以下:app
<?php class UserLogin extends \yii\db\ActiveRecord { /** * @inheritdoc */ public static function tableName() { return 'user_login'; } /** * @inheritdoc */ public function rules() { return [ [['user_id'], 'integer'], [['type'], 'string', 'max' => 30], [['qq_access_token', 'wx_access_token'], 'string', 'max' => 220], [['qq_openid', 'wx_openid'], 'string', 'max' => 100] ]; } /** * @inheritdoc */ public function attributeLabels() { return [ 'id' => Yii::t('yii', 'ID'), 'user_id' => Yii::t('yii', 'User ID'), 'type' => Yii::t('yii', 'Type'), 'qq_access_token' => Yii::t('yii', 'Qq Access Token'), 'qq_openid' => Yii::t('yii', 'Qq Openid'), 'wx_access_token' => Yii::t('yii', 'Wx Access Token'), 'wx_openid' => Yii::t('yii', 'Wx Openid'), ]; } }
三、控制器裏的方法以下:
QQ登陸yii
public function actionQqLogin() { $_model = new UserLogin(); $model = new TUser(); $post = Yii::$app->request->post(); if(!empty($post)) { $t_nickname = !empty($post['t_nickname']) ? trim($post['t_nickname']) : ''; $access_token = !empty($post['access_token']) ? trim($post['access_token']) : ''; $openid = !empty($post['openid']) ? trim($post['openid']) : ''; $t_photo = !empty($post['t_photo']) ? trim($post['t_photo']) : '';//頭像 $res = UserLogin::find() ->where(['type'=>'qq','qq_openid'=>$openid]) ->one(); //判斷是否已存在用戶信息,存在則返回該條用戶信息 if(!empty($res)) { $res->qq_access_token = $access_token; $res->save(); //獲取一條用戶信息 $user = $model->getUserrow($res->user_id); if(!empty($user)){ return $user; }else{ ErrorMsg::Info(Yii::t('yii','Login fail')); } }else{ //保存新用戶 $user = $this->saveUser($t_nickname,$t_nickname,$openid,'','',$t_photo); if(empty($return['error_code'])){ $_model->user_id = $user->t_id; $_model->type = 'qq'; $_model->qq_access_token = $access_token; $_model->qq_openid = $openid; $_model->save(); $user = $model->getUserrow($user->t_id); //保證返回數據字段一致 } return $user; } }else{ ErrorMsg::Info(Yii::t('yii','Login fail')); } }
微信登陸post
public function actionWxLogin() { $_model = new UserLogin(); $model = new TUser(); $post = Yii::$app->request->post(); if(!empty($post)) { $t_nickname = !empty($post['t_nickname']) ? trim($post['t_nickname']) : ''; $access_token = !empty($post['access_token']) ? trim($post['access_token']) : ''; $openid = !empty($post['openid']) ? trim($post['openid']) : ''; $t_photo = !empty($post['t_photo']) ? trim($post['t_photo']) : '';//頭像 $res = UserLogin::find() ->where(['type'=>'weixin','wx_openid'=>$openid]) ->one(); //判斷是否已存在用戶信息,存在則返回該條用戶信息 if(!empty($res)) { $res->wx_access_token = $access_token; $res->save(); //獲取一條用戶信息 $user = $model->getUserrow($res->user_id); if(!empty($user)){ return $user; }else{ ErrorMsg::Info(Yii::t('yii','Login fail')); } }else{ //保存新用戶 $user = $this->saveUser($t_nickname,$t_nickname,$openid,'','',$t_photo); if(empty($return['error_code'])){ $_model->user_id = $user->t_id; $_model->type = 'weixin'; $_model->wx_access_token = $access_token; $_model->wx_openid = $openid; $_model->save(); $user = $model->getUserrow($user->t_id);//保證返回數據字段一致 } return $user; } }else{ ErrorMsg::Info(Yii::t('yii','Login fail')); } }
保存用戶信息方法:網站
public function saveUser($t_username,$t_nickname,$openid,$email,$phone,$t_photo) { $access_token = sha1(time().$openid); $data = array( "t_nickname"=> $t_nickname, "t_password"=> base64_encode($openid), "t_state" => 0, "t_photo" => $t_photo?$t_photo:"/images/upload/100x100/no_photo.jpg", "t_timezone"=> "PRC", "t_language"=> "zh_cn", "access_token"=> $access_token, "rent_user_type"=>"3", 't_add_time'=>time(), ); $model = new $this->modelUser; $model->attributes = $data; if(!empty($t_nickname) && !empty($openid)){ if(!$model->save()){ ErrorMsg::Info(Yii::t('yii','Reg fail')); } return $model; }else{ ErrorMsg::Info(Yii::t('yii','m-log-2')); } }
第三方登陸獲取用戶基本信息方法,TUser model裏:ui
public function getUserrow($uid) { $user = $this->find() ->select(['access_token','t_password']) ->where(['t_id'=>$uid]) ->one(); if(!empty($user)){ $result['access_token']= !empty($access_token=$user->access_token)?$access_token:""; $result['appsercert'] = !empty($t_password=$user->t_password)?$t_password:""; return $result; //返回給手機端用,只返回access_token和appsercert。 } }
好了,到這裏Restfual api 架構的第三方登陸已經實現了,微博,淘寶等第三方登陸實現的思路也如此,就是要對傳入的參數進行改進一下就OK了。這是我實現Restfual api架構的第三方登陸的思路,不足的提議,好的點贊哈,咱們一塊兒交流。this
一、直接在user表裏加上QQ、weixin的type,openid和access_token字段,這種作法拓展性很差,之後要是再增長如:微博,淘寶等第三方登陸的話,又要操做user表,對user表操做過於頻繁容易出問題,並且也不是每個用戶都會使用第三方登陸,會形成大量空缺字段,浪費。我之因此獨立建立user_login表也正是基於這些考慮的。二、返回給手機端全部的用戶信息。其實手機端不須要那些,你只要返回給手機端access_token和appsercert這兩個字段就能夠了,手機端會本身獲取用戶信息。