綁定QQ登錄 PHP OAuth詳解

越來越多的網站開始採用 第三方賬號登錄 如qq 微博 開心網 等諸多流行的社交平臺

利用第三方賬號登錄,可以更好地省去用戶的註冊時間,並且極大地提高用戶體驗,吸引更多的潛在用戶。

讓用戶擁有 一個號碼走web天下的感覺。。。

對我們開發者來說 這也是一個主要的學習新知識點 主要原理即Oauth。

 

 

OAUTH協議爲用戶資源的授權提供了一個安全的、開放而又簡易的標準。與以往的授權方式不同之處是OAUTH的授權不會使第三方觸及到用戶的帳號信息(如用戶名與密碼),即第三方無需使用用戶的用戶名與密碼就可以申請獲得該用戶資源的授權,因此OAUTH是安全的。

 步驟詳細介紹

 

1.去qq、微博的第三方開發平臺 去review一下他們的API

2.申請AppId和AppKey ,對於qq來說 網址 http://connect.opensns.qq.com/ 點擊首頁的 <網站接入>

註冊自己的開發者信息 隨便百度一下 輸入一個備案號 即可 然後我們就可以獲得 AppId和AppKey

3.然後就是編寫代碼

<?php
/**
 * 申請http://connect.opensns.qq.com/apply
 * 列表http://connect.opensns.qq.com/my
 */
session_start();
$qq_oauth_config = array(
	'oauth_consumer_key'=>'*******',//APP ID
	'oauth_consumer_secret'=>'******************',//APP KEY
	'oauth_callback'=>"http://www.955.cc/qq.php?action=reg",//這裏修改爲當前腳本
	'oauth_request_token_url'=>"http://openapi.qzone.qq.com/oauth/qzoneoauth_request_token",
	'oauth_authorize_url'=>'http://openapi.qzone.qq.com/oauth/qzoneoauth_authorize',
	'oauth_request_access_token_url'=>'http://openapi.qzone.qq.com/oauth/qzoneoauth_access_token',
	'user_info_url' => 'http://openapi.qzone.qq.com/user/get_user_info',
);
$action = isset($_GET['action']) ? $_GET['action'] : '';


$qq = new qq_oauth($qq_oauth_config);
switch($action){
	//用戶登錄 Step1:請求臨時token
	case 'login':
		$token = $qq->oauth_request_token();
		$_SESSION['oauth_token_secret'] = $token['oauth_token_secret'];
		$qq->authorize($token['oauth_token']);
	break;
	//Step4:Qzone引導用戶跳轉到第三方應用
	case 'reg':
		$qq->register_user();
		$access_token = $qq->request_access_token();
		if($token = $qq->save_access_token($access_token)){
			//保存,一般發給用戶cookie,以及用戶入庫
			//var_dump($token);
			$_SESSION['oauth_token'] = $token['oauth_token'];
			$_SESSION['oauth_token_secret'] = $token['oauth_token_secret'];
			$_SESSION['openid'] = $token['openid'];
			header('Content-Type: text/html; charset=utf-8');
			$user_info = json_decode($qq->get_user_info());
			if($user_info->ret!=0){
				exit("獲取頭像暱稱時發生錯誤".$user_info->msg);
			} else {
				echo 'QQ暱稱:',$user_info->nickname,
				'<img src="',$user_info->figureurl,'" />',
				'<img src="',$user_info->figureurl_1,'" />',
				'<img src="',$user_info->figureurl_2,'" />';
			}
			
		}
	break;
	default :
}


class qq_oauth{
	private $config;
	function __construct($config){
		$this->config = $config;
	}
	/**
	 * 返回配置
	 * @param string $name
	 * 
	 */
	function C($name){
		return isset($this->config[$name]) ?  $this->config[$name] : FALSE;
	}
	/**
	 * 構建請求URL
	 * @param string $url
	 * @param array $params
	 * @param string $oauth_token_secret
	 * 
	 */
	function build_request_uri($url,$params=array(),$oauth_token_secret=''){
		$oauth_consumer_key = $this->C('oauth_consumer_key');
		$oauth_consumer_secret = $this->C('oauth_consumer_secret');
		
		$params = array_merge(array(
			'oauth_version'=>'1.0',
			'oauth_signature_method'=>'HMAC-SHA1',
			'oauth_timestamp'=>time(),
			'oauth_nonce'=>rand(1000,99999999),
			'oauth_consumer_key'=>$oauth_consumer_key,
		),$params);
		$encode_params = $params;
		ksort($encode_params);
		$oauth_signature = 'GET&'.urlencode($url).'&'.urlencode(http_build_query($encode_params));
		$oauth_signature = base64_encode(hash_hmac('sha1',$oauth_signature,$oauth_consumer_secret.'&'.$oauth_token_secret,true));
		$params['oauth_signature'] = $oauth_signature;
		return $url.'?'.http_build_query($params);
	}
	/**
	 * 校驗回調是否返回約定的參數 
	 */
	function check_callback(){
		if(isset($_GET['oauth_token']))
			if(isset($_GET['openid']))
				if(isset($_GET['oauth_signature']))
					if(isset($_GET['timestamp']))
						if(isset($_GET['oauth_vericode']))
							return true;
		return false;
	}
	
	function get_contents($url){
		$curl = curl_init();
		curl_setopt($curl,CURLOPT_RETURNTRANSFER,true);
		curl_setopt($curl,CURLOPT_URL,$url);
		return curl_exec($curl);
	}
	/**
	 * Step1:請求臨時token、Step2:生成未授權的臨時token
	 */
	function oauth_request_token(){
		$url = $this->build_request_uri($this->C('oauth_request_token_url'));
		$tmp_oauth_token = $this->get_contents($url);
		parse_str($tmp_oauth_token);
		/*
		oauth_token	未授權的臨時token
		oauth_token_secret	token的密鑰,該密鑰僅限於臨時token
		error_code	錯誤碼
		*/
		if(isset($error_code)) exit($error_code);
		return array(
			'oauth_token'=>$oauth_token,
			'oauth_token_secret'=>$oauth_token_secret
		);
	}
	/**
	 * Step3:引導用戶到Qzone的登錄頁
	 * @param string $oauth_token 未授權的臨時token
	 */
	function authorize($oauth_token){
		$str = "HTTP/1.1 302 Found";
		header($str);
		$url = $this->C('oauth_authorize_url');
		$query_strings = http_build_query(array(
			'oauth_consumer_key'=>$this->C('oauth_consumer_key'),
			'oauth_token'=>$oauth_token,
			'oauth_callback'=>$this->C('oauth_callback'),
		));
		header('Location: '.$url.'?'.$query_strings);
	}
	/**
	 * Step4:Qzone引導用戶跳轉到第三方應用
	 * @return bool 驗證是否有效 
	 */
	function register_user(){
		/*
		 * oauth_token	已授權的臨時token
		 * openid	騰訊用戶對外的統一ID,該OpenID與用戶QQ號碼一一對應
		 * oauth_signature	簽名值,方便第三方來驗證openid以及來源的可靠性。
		 * 		使用HMAC-SHA1算法:
		 * 		源串:openid+timestamp(串中間不要添加'+'符號)
		 * 		密鑰:oauth_consumer_secret
		 * timestamp	openid的時間戳
		 * oauth_vericode	授權驗證碼。
		 */
		if($this->check_callback()){
			//校驗簽名
			$signature = base64_encode(hash_hmac('sha1',$_GET['openid'].$_GET['timestamp'],$this->C('oauth_consumer_secret'),true));
			if(!empty($_GET['oauth_signature']) && $signature==$_GET['oauth_signature']){
				$_SESSION['oauth_token'] = $_GET['oauth_token'];
				$_SESSION['oauth_vericode'] = $_GET['oauth_vericode'];
				return;
			}
		}
		//校驗未通過
		exit('UNKNOW REQUEST');
	}
	/**
	 * Step5:請求access token 
	 */
	function request_access_token(){
		$url = $this->build_request_uri($this->C('oauth_request_access_token_url'),array(
			'oauth_token'=>$_SESSION['oauth_token'],
			'oauth_vericode'=>$_SESSION['oauth_vericode']
		),$_SESSION['oauth_token_secret']);
		return $this->get_contents($url);
	}
	/**
	 * Step6:生成access token (保存access token)
	 * 
	 * 關於access_token
	 * 目前access_token(及其secret)是長期有效的,和某一個openid對應,目前可以支持線下獲取該openid的信息。 
	 * 當然,用戶有權限在Qzone這邊刪除對第三方的授權,此時該access_token會失效,需要重新走整個流程讓用戶授權。
	 * 以後會逐步豐富access_token的有效性,長期有效、短期有效、用戶登錄時纔有效等。
	 */
	function save_access_token($access_token_str){
		parse_str($access_token_str,$access_token_arr);
		if(isset($access_token_arr['error_code'])){
			return FALSE;
		} else {
			return $access_token_arr;
		}
	}
	/**
	 * 目前騰訊僅開放該API
	 * 獲取登錄用戶信息,目前可獲取用戶暱稱及頭像信息。
	 * http://openapi.qzone.qq.com/user/get_user_info
	 */
	function get_user_info(){
		$url = $this->build_request_uri($this->C('user_info_url'),array(
			'oauth_token'=>$_SESSION['oauth_token'],
			'openid'=>$_SESSION['openid'],
		),$_SESSION['oauth_token_secret']);
		return $this->get_contents($url);
	}
}

 

發佈了48 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章