欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

绑定QQ登录 PHP OAuth详解

程序员文章站 2022-03-02 21:09:01
...

越来越多的网站开始采用 第三方账号登录 如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);
	}
}