PHP/ThinkPHP5制作QQ第三方登录,无需官方SDK文件

03,10 1292 ℃ 13
             

第三方授权登录是目前web和app应用中非常受欢迎的用户登录方式,也是必不可少的功能,QQ第三方登录更是普遍;无需注册,QQ一键授权登录,简单便捷。那么,PHP/ThinkPHP5该怎么制作QQ第三方授权登录呢?


1、新建一个控制器,命名为User

namespace app\index\controller;
use think\Config;
use think\Session;
use think\Cookie;
use think\Db;
class User extends \think\Controller
{
    public function login(){
        if(Cookie::has('user')) {
          $user = Db::name('user')->where(['login_string'=>Cookie::get('user')])->find();
          if(empty($user)){
            Cookie::delete('user');
          } else {
            $this->redirect('index/index/index');
          }
        }
        //把第一次访问之前的url存入Session待用
        if(!Session::has('user_url')){
            Session::set('user_url',$this->request->param('url'));
        }
        $config = Config::get('thirdlogin.qq');
        // 获取回调地址
        $url = $config['callback'];
        $redirect_uri = urlencode($url);
        
        $appid = $config['appid'];
        $appsecret = $config['appsecret'];
        
        Session::set('state',md5(uniqid(rand(), TRUE)));
         // 获取code码,用于和QQ服务器申请token。 注:依据OAuth2.0要求,此处授权登录需要用户端操作
         if(empty($this->request->param('code')) && !Session::has('code')){
           //以下信息可安放在用户登录界面上:
          $url= 'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id='.$appid.'&redirect_uri='.$redirect_uri.'&scope=get_user_info&state='.Session::get('state');
          header('Location:'.$url);//跳转到第三方登录入口
          exit;
         }
         // 依据code码去获取openid和access_token,自己的后台服务器直接向QQ服务器申请即可
         if (!empty($this->request->param('code')) && !Session::has('token')){
            Session::set('code',$this->request->param('code'));
            $url="https://graph.qq.com/oauth2.0/token?client_id=".$appid.
             "&client_secret=".$appsecret."&code=".Session::get('code')."&grant_type=authorization_code"
             ."&state=".Session::get('state')."&redirect_uri=".$redirect_uri;
            $res = $this->https_request($url);
            $res = explode("&",$res);
            $token = [];
            foreach ($res as $k => $val) {
              $val = explode("=",$val);
              $token[$val[0]] = $val[1];
            }
         }
         // 依据申请到的access_token和openid,申请Userinfo信息。
         if (isset($token['access_token'])){
          $url = "https://graph.qq.com/oauth2.0/me?access_token=".$token['access_token'];
          $openid = $this->https_request($url);
          if (preg_match('/\"openid\":\"(\w+)\"/i', $openid, $match)) { 
            $openid = $match[1]; 
          }
          $url = "https://graph.qq.com/user/get_user_info?oauth_consumer_key=".$appid."&access_token=".$token['access_token']."&openid=".$openid.'&format=json';
          
          $userinfo = $this->https_request($url);
          $userinfo = json_decode($userinfo,true);
          Session::delete('code');
          Session::delete('state');
          $user_url = Session::get('user_url');
          Session::delete('user_url');
          //从这里开始根据自己的程序修改
          if(!empty($userinfo)){
              $user = Db::name('user')->where(['openid'=>$openid])->find();
              $salt = salt(create_code(20));
              if(empty($user)) {
                if($user['status'] == -1) {
                  return $this->error('你已被拉黑');
                }
                $data = [
                  'name' => $userinfo['nickname'],
                  'openid' => $openid,
                  'gender' =>$userinfo['gender'],
                  'thumb' => $userinfo['figureurl_qq_1'],
                  'login_string' => $salt,
                  'create_time' => time(),
                  'last_login_time' => time(),
                  'last_login_ip' => $this->request->ip(),
                  'login_num' => 1,
                ];
                if(false == Db::name('user')->insert($data)){
                  return $this->error('登录失败');
                }
              } else {
                if(false == Db::name('user')->where('id',$user['id'])->update(['login_string'=>$salt,'last_login_time'=>time(),'last_login_ip'=>$this->request->ip(),'login_num'=>$user['login_num']+1])) {
                  return $this->error('登录失败');
                }
              }
              Cookie::set('user',$salt,7200);
              $this->redirect($user_url);
          } else {
            return $this->error('未知错误');
          }
          //这里结束
       }
    }
   protected function https_request($url, $data = null)
   {
      $curl = curl_init();
      curl_setopt($curl, CURLOPT_URL, $url);
      curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
      curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
      if (!empty($data)){
       curl_setopt($curl, CURLOPT_POST, 1);
       curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
      }
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
      $output = curl_exec($curl);
      curl_close($curl);
      return $output;
   }
}

以上代码就是本博客的登录代码,部分内容需根据自己程序的需要进行修改后才能使用。


2、在配置文件中加入相应的配置

//QQ第三方登录
'thirdlogin'=>[
'qq'        => [
'appid'     => '',
'appsecret' =>'',
'callback'  =>'',//回调地址
],

以上配置项均需要填入你申请到的配置项(具体怎么申请我就不说了),回调地址填写为你新建的User控制器里的login()方法。


3、如果你是非ThinkPHP5的PHP程序,把代码里的Session、Cookie等方法改成PHP原生的即可。


注意:在请求新建的User控制器的login()方法时,需要传递一个参数user_url,作为用户在完成登录后的跳回页面,这个参数的值建议为用户请求登录的页面地址。

提交发言 登录

  • 回复ta 本熊 2018-04-26 09:13:18

  • 回复ta 听雨 2018-03-15 08:27:08

    @宋小强,@自己没有提示的,点右边的回复ta就能@了

  • 回复ta Qel 2018-03-15 00:26:55

    @宋小强 123

  • 回复ta 宋小强 2018-03-15 00:25:41

    @宋小强 可以@自己吗?

  • 回复ta 宋小强 2018-03-15 00:24:39

    如何@啊 >;br/>;

  • 回复ta 听雨 2018-03-14 15:29:15

    @青,hi,青姐,关注您的博客好久了,我是您的粉丝哦

  • 回复ta 2018-03-14 15:25:50

    仿佛真的听见了下雨声

  • 回复ta 听雨 2018-03-12 09:27:11

    @不知不觉,体验下被@的感觉吧

  • 回复ta 不知不觉 2018-03-12 09:15:23

  • 回复ta 听雨 2018-03-12 08:30:16

    @土、豆,后台的功能没有完善,包括菜单管理,会员管理,评论管理等;等我抽空把这些完善了或许会考虑分享出来的哈。