第三方登录(二)新浪微博登录

应用微博作为第三方网站登录的方式也非常广泛,下面开始接入。

成为开发者

登录开放平台,填写信息,并实名认证,成为开发者:

https://open.weibo.com/developers

申请网站接入,创建应用

https://open.weibo.com/connect

原理介绍

原理和上篇文章QQ登录基本是一样的,先授权获取code,再用code获取access_token和uid,最后用access_token和uid获取获取用户信息。

官方强调,第三方应用应该用access_token和自己应用内的用户建立唯一映射关系,来识别登录状态,不能使用返回值里的UID字段来做登录识别,因为一个用户对应接口返回的uid是一成不变的,这样会很不安全,而access_token是有时效的,默认一小时过期。因此,开发者不能单凭接口获取到的uid来查询用户信息,并验证登录,而应该通过这两个参数获取用户信息,这样才算真正完成了授权。

编写代码

Home模块Weibologin控制器:

<?php
namespace Home\Controller;

use Api\Controller\WeibologinController as Weibologinapi;
use Vendor\Page;

class WeibologinController extends ComController
{
    public function weibo_login()
    {
        $Oauth = new Weibologinapi();
        //第一步:授权并获取code
        $Oauth -> weibo_login();
    }

    //回调
    public function callback()
    {
        $Oauth = new Weibologinapi();
        //第二步:通过code获取access_token和uid
        $token = $Oauth -> weibo_callback();
        $access_token = $token['access_token'];
        $uid = $token['uid'];
        //第三步:通过access_token和uid获取用户信息
        $user_info = $Oauth -> get_user_show();
        $exist = M('user') -> where(['wb_uid' => $user_info['idstr']]) -> getField('id');
        if($exist){
            session('uid',$exist);
            $this -> redirect('Home/Index/index');
        }else{
            //将信息插入数据库
            $data['nickname'] = $user_info['screen_name'];
            $data['avatar'] = $user_info['profile_image_url'];
            $data['addtime'] = time();
            $data['wb_uid'] = $user_info['idstr'];
            $res = M('user') -> data($data) -> add();
            if($res){
                session('uid',$res);
                $this -> redirect('Home/Index/index');
            }
        }
    }

    //用户取消授权的回调
    public function redirect_cancel()
    {
        //TODO:页面跳转
    }
}

Api模块Weibologin控制器:

<?php

namespace Api\Controller;

use Vendor\Page;
use Think\Controller;

class WeibologinController extends Controller
{
    const GET_AUTH_CODE_URL = "https://api.weibo.com/oauth2/authorize";
    const GET_ACCESS_TOKEN_URL = "https://api.weibo.com/oauth2/access_token";
    const GET_USER_INFO = "https://api.weibo.com/2/users/show.json";

    public function weibo_login()
    {
        //-------生成唯一随机串防CSRF攻击
        $state = md5(uniqid(rand(), TRUE));
        session('state',$state);
        $params = array(
            "client_id" => C('WB_APPKEY'),
            "redirect_uri" => C('WB_CALLBACK'),
            "state" => session('state')
        );
        $login_url = self::GET_AUTH_CODE_URL.'?'.http_build_query($params);
        header("Location:$login_url");
    }

    public function weibo_callback(){
        //--------验证state防止CSRF攻击
        if($_GET['state'] != session('state')){
            return false;
        }
        //-------请求参数列表
        $keysArr = array(
            "client_id" => C('WB_APPKEY'),
            "client_secret" => C('WB_APPSECRET'),
            "grant_type" => "authorization_code",
            "code" => $_GET['code'],
            "redirect_uri" => C('WB_CALLBACK')
        );
        $data = array();
        //------构造请求access_token的url
        $token_url = self::GET_ACCESS_TOKEN_URL.'?'.http_build_query($keysArr);
        $response = $this->post($token_url,$data);
        $msg = json_decode($response,true);
        if(isset($msg['error'])){
            $this->showError($msg->error, $msg->error_description);
        }
        $token['access_token']=$msg['access_token'];
        $token['uid']=$msg['uid'];
        session('access_token',$msg['access_token']);
        session('wb_uid',$msg['uid']);
        return $token;
    }

    //获取用户信息
    public function get_user_show()
    {
        $access_token = session('access_token');
        $wb_uid = session('wb_uid');
        if(!$access_token || !$wb_uid){
            return false;
        }
        $keysArr = array(
            "access_token" => $access_token,
            "uid" => $wb_uid //
        );
        //------构造请求user_info的url
        $token_url = self::GET_USER_INFO.'?'.http_build_query($keysArr);
        $response = $this->get_contents($token_url);
        $userinfo = json_decode($response,true);
        return $userinfo;
    }

    public function get_contents($url){
        if (ini_get("allow_url_fopen") == "1") {
            $response = file_get_contents($url);
        }else{
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($ch, CURLOPT_URL, $url);
            $response = curl_exec($ch);
            curl_close($ch);
        }
        if(empty($response)){
            return false;
        }
        return $response;
    }

    public function post($url, $keysArr, $flag = 0){
        $ch = curl_init();
        if(! $flag) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $keysArr);
        curl_setopt($ch, CURLOPT_URL, $url);
        $ret = curl_exec($ch);
        curl_close($ch);
        return $ret;
    }

    /**
     * showError
     * 显示错误信息
     * @param int $code 错误代码
     * @param string $description 描述信息(可选)
     */
    public function showError($code, $description = '
){
        echo "<meta charset=\"UTF-8\">";
        echo "<h3>error:</h3>$code";
        echo "<h3>msg :</h3>$description";
        exit();
    }
}

config.php:

<?php
return array(//'配置项'=>'配置值'
    //微博登录配置
    'WB_APPKEY' => '应用后台App Key',
    'WB_APPSECRET' => '应用后台App Secret',
    'WB_CALLBACK' => 'https://example.acier.cn/index.php/Api/Weibologin/redirect_url'
);

发表评论

发表回复

沙发空缺中,还不快抢~