oauth1.a&2.0以get,head,post请求access_token[php]
2011-10-24 23:23
501 查看
忽如一夜春风来,千万开放平台开。然而开放平台不是开房平台,你需要先申请一个叫access_token的东东。这个东西就是你在开放平台上的应用(consumer)、开放平台、使用你的应用来访问自身数据客户的一个三方契约;契约写明本用户允许consumer访问本用户在开房平台上的数据;consumer每次拿着这个契约给开房平台看一下,就可以大摇大摆的取得想要的数据了。
取得access token常用的有两种方法:oauth1.a和oauth2.0(本来存在oauth1.0,后来因为安全性问题被弃用)。流程开始之前,你必须为你的应用申请一个consumer_key(任意申请key和token都会附带secret,secret在2.0里面基本没啥用),consumer_key用于申请,consumer_secret+当前其他token附带的secret用于提取传输参数的签名,校验正确性。
oauth1.a是一种比较繁琐的认证流程。它要先使用consumer_key申请一个未授权的request token,用户授权之后变为授权的request token并生成一个verified以get方式送到应用的回调地址(无回调地址即ood,会发送一个pin code到浏览器),然后应用将发送授权的request_token(事实上和未授权的一样,因此上步不存在新的secret)+verified申请access_token.
之后调用api时需要将access token+函数参数+(consumer_secret+access_secret)提取签名发送到开房平台,开放平台将函数结果返回。
oauth2一种存在4中方式申请,采用了https加密,因此不用个人手动提取签名,且认证步骤简化,所以说简单很多。另外,其返回结果通常是以json格式返回。在此就不一一解释了。
Http请求数据可以有多种方式,在开放平台中接受三种: post, get, head. post将数据放在http请求体中,get将请求数据放在网址中和网址以?分割,head不是head request是把请求放在head中,实验表明其方式是get. 具体实验写在后面。由于get是将所有数据以近乎于明文的方式拼接到网址,因此post,head相对安全点,所以在发送某些敏感数据时推荐使用post。
============================================烦人的理论到此为止=============================================================
在oauth1.a&2.0申请token过程中,需要发送多次http请求,有些需要请求需要浏览器重定向。所以先封装各种不同的用于发送的http请求的类,使用了一个工厂,方便调用不同的请求方式。
--------------------------------------oauth1.a----------------------------------------------------------
url->base string类;签名类:
--待续--
取得access token常用的有两种方法:oauth1.a和oauth2.0(本来存在oauth1.0,后来因为安全性问题被弃用)。流程开始之前,你必须为你的应用申请一个consumer_key(任意申请key和token都会附带secret,secret在2.0里面基本没啥用),consumer_key用于申请,consumer_secret+当前其他token附带的secret用于提取传输参数的签名,校验正确性。
oauth1.a是一种比较繁琐的认证流程。它要先使用consumer_key申请一个未授权的request token,用户授权之后变为授权的request token并生成一个verified以get方式送到应用的回调地址(无回调地址即ood,会发送一个pin code到浏览器),然后应用将发送授权的request_token(事实上和未授权的一样,因此上步不存在新的secret)+verified申请access_token.
之后调用api时需要将access token+函数参数+(consumer_secret+access_secret)提取签名发送到开房平台,开放平台将函数结果返回。
oauth2一种存在4中方式申请,采用了https加密,因此不用个人手动提取签名,且认证步骤简化,所以说简单很多。另外,其返回结果通常是以json格式返回。在此就不一一解释了。
Http请求数据可以有多种方式,在开放平台中接受三种: post, get, head. post将数据放在http请求体中,get将请求数据放在网址中和网址以?分割,head不是head request是把请求放在head中,实验表明其方式是get. 具体实验写在后面。由于get是将所有数据以近乎于明文的方式拼接到网址,因此post,head相对安全点,所以在发送某些敏感数据时推荐使用post。
============================================烦人的理论到此为止=============================================================
在oauth1.a&2.0申请token过程中,需要发送多次http请求,有些需要请求需要浏览器重定向。所以先封装各种不同的用于发送的http请求的类,使用了一个工厂,方便调用不同的请求方式。
sender.php
<?php abstract class Sender{ public abstract function send($url, $data); } abstract class GetSender extends Sender{ protected function makeUrl($aUrl, $data){ $url=$aUrl.'?'; foreach($data as $key=>$value){ if($url.chr(strlen($url)-1)!='?'){ $url.='&'; } $url=$url.$key.'='.$value; } return $url; } } abstract class PostSender extends Sender{ } abstract class HeadSender extends Sender{ protected function makeHead($data){ $head = array(); if(array_key_exists('oauth_version', $data) && $data['oauth_version']=='1.0'){ $head[0] = 'Authorization: OAuth '; }else{ $head[0] = 'Authorization: OAuth2 '; } foreach($data as $key=>$value){ $head[0] = $head[0].$key.'='.$value.','; } $head[0][strlen($head[0])-1]=null; return $head; } } class RedirectGetSender extends GetSender{ public function send($url, $data){ $url = $this->makeUrl($url, $data); header("Location:$url"); } } class DirectGetSender extends GetSender{ public function send($url, $data){ $url = $this->makeUrl($url, $data); $result = file_get_contents($url); return $result; } } class RedirectPostSender extends PostSender{ public function send($url, $data){ echo "click submit to authorize!<br>"; echo '<form action="'.$url.'" method="post">'; foreach($data as $key=>$value){ echo '<input type="hidden" name='.$key.' value="'.$value.'"/>'; } echo '<input type="submit" value="SBUMIT">'; echo '</form>'; } } class DirectPostSender extends PostSender{ public function send($url, $data){ $curlHandle = curl_init(); curl_setopt($curlHandle, CURLOPT_URL, $url); curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); curl_setopt($curlHandle, CURLOPT_HTTPHEADER, array('Expect:')); curl_setopt($curlHandle, CURLOPT_POST, true); curl_setopt($curlHandle, CURLOPT_POSTFIELDS, http_build_query($data)); $result = curl_exec($curlHandle); curl_close($curlHandle); return $result; } } class DirectHeadSender extends HeadSender{ public function send($url, $data){ $head = $this->makeHead($data); $curlHandle = curl_init(); curl_setopt($curlHandle, CURLOPT_URL, $url); curl_setopt($curlHandle, CURLOPT_HEADER, false); curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $head); curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curlHandle, CURLOPT_FRESH_CONNECT, 1); $result = curl_exec($curlHandle); curl_close($curlHandle); return $result; } } class RedirectHeadsender extends HeadSender{ public function send($url, $data){ echo "There are no head method for this redirect request!<br>"; } } class SenderFactory{ public static function createSender($isRedirect, $mode){ switch (strtolower($mode)){ case "get": if($isRedirect===true){ return new RedirectGetSender(); }else{ return new DirectGetSender(); } break; case "post": if($isRedirect===true){ return new RedirectPostSender(); }else{ return new DirectPostSender(); } break; case "head": if($isRedirect ===true){ return new RedirectHeadSender(); }else{ return new DirectHeadSender(); } break; } } } ?>
--------------------------------------oauth1.a----------------------------------------------------------
url->base string类;签名类:
url.php
<?php class Helper_URL { /** * * Build HTTP Query * * * * @param array $params Name => value array of * parameters * * * * @return string HTTP query * */ public static function buildHttpQuery(array $params) { if (empty($params)) { return ''; } $keys = self::urlEncode(array_keys($params)); $values = self::urlEncode(array_values($params)); $params = array_combine($keys, $values); uksort($params, 'strcmp'); $pairs = array(); foreach ($params as $key => $value) { $pairs[] = $key . '=' . $value; } return implode('&', $pairs); } /** * * URL Encode * * * * @param mixed $item string or array of items * to url encode; * * * * @return mixed url encoded string * or array of strings * */ public static function urlEncode($item) { static $search = array('%7E'); static $replace = array('~'); if (is_array($item)) { return array_map(array(__CLASS__, 'urlEncode'), $item); } if (is_scalar($item) === false) { return $item; } return str_replace($search, $replace, rawurlencode($item)); } /** * * URL Decode * * * * @param mixed $item Item to url decode * * * * @return string URL decoded string * */ public static function urlDecode($item) { if (is_array($item)) { return array_map(array(__CLASS__, 'urlDecode'), $item); } return rawurldecode($item); } } ?>
signature.php
<?php include_once('url.php'); /* * This class is used to generate the signature of base string. * $url is the url your request will be sended to. and if in 'get' mode it is * only the part before '?'; * $reqMod is request mode: 'get', 'post'; when paremeters are put in the head, * its request mode is 'get'; * $params are all the params except 'oauth_signature'; * $consumerSecret is your consumer_secret; * $token_secret is the secret you got in the nearest formal step; */ class Signaturer{ public function getSignature($url, $reqMode, array $params, $consumerSecret, $tokenSecret=''){ $baseStr = $this->getBaseStr($reqMode, $url, $params); if(isSet($params['oauth_signature_method'])){ $signMethod = $this->getSignMethod($params['oauth_signature_method']); }else{ $signMethod = 'sha1'; } $key = $this->getKey($consumerSecret, $tokenSecret); return base64_encode(hash_hmac($signMethod, $baseStr, $key, true)); } /* used for constructing the base string. * */ public function getBaseStr($method, $url, $params){ if (array_key_exists('oauth_signature', $params)) { unset($params['oauth_signature']); } $urlParts = explode('?', $url); $parts = array(strtoupper($method), $urlParts[0], Helper_URL::buildHTTPQuery($params)); return implode('&', Helper_URL::urlEncode($parts)); } /* * used to analyse signature method automatically * */ public function getSignMethod($signMethod){ list($begin, $end) = explode('-', $signMethod); return strtolower($end); } /* * create key for signature; * in the first step, since there is no secret, it is "$consumerSecret&" * */ public function getKey($consumerSecret, $tokenSecret = ''){ $secrets = array($consumerSecret, $tokenSecret); return implode('&', Helper_URL::urlEncode($secrets)); } } ?>
oauthTokenFetcher.php
<?php include_once('sender.php'); include_once('signaturer.php'); /* * to apply an access_token, there are three step: * 1. consumer (get post head) a request for unauthorised_request_token and an * unauthorizised request token would be sended back; * 2. consumer redirect to the authorization center url; * 3. consumer get the authorized request token in the callback url; and then * consumer (get post head) a request for access token; finally, an access * token is sended back; */ class OauthTokenFetcher{ private $signaturer; function __construct(){ $this->signaturer = new Signaturer(); } public function setNonceStamp(array &$params){ $params['oauth_nonce'] = md5(mt_rand()); $params['oauth_timestamp'] = time(); } public function fetchToken($url, $reqMode, array $params, $consumerSecret, $tokenSecret, $tokenStyle='request_token'){ $reqParam = strtolower($reqMode)==='head'?'get':$reqMode; $params['oauth_signature'] = $this->signaturer->getSignature($url, $reqParam, $params, $consumerSecret, $tokenSecret); foreach($params as $key=>$value){ $params[$key] = Helper_URL::urlEncode($value); } if($tokenStyle === 'request_token'){ $sender = SenderFactory::createSender(true, $reqMode); $sender->send($url, $params); }else{ $sender = SenderFactory::createSender(false, $reqMode); $result = $sender->send($url, $params); return $result; } } /* * parse return of fetchToken * */ public function parse($str){ $infoTmps = explode('&', $str); $info = array(); foreach($infoTmps as $value){ list($begin, $end) = explode('=', $value); $info[$begin] = $end; } return $info; } } ?>
--待续--
相关文章推荐
- 微信公众号:1-IDHTTP控件:GET/POST 请求获取access_token
- PHP post & get请求
- PHP发起get post put delete请求
- HTTP的请求方法一共有9种,有OPTIONS, HEAD, GET, POST等等(消息头有图,十分清楚)
- 怎么用PHP发送HTTP请求(POST请求、GET请求)?
- 用jquery向服务器发送请求get&post
- php发送get、post请求的几种方法 以及获取内容
- HTTP协议中POST、GET、HEAD、PUT等请求方法以及一些常见错误
- AFNetworking2.0简易GET,POST请求封装以及使用
- PHP 使用curl库来发送GET,POST请求,处理json格式数据
- PHP中使用cURL实现Get和Post请求的方法
- HTTP协议中POST、GET、HEAD、PUT等请求方法以及一些常见错误
- post&get请求编码问题
- Retrofit2.0的get post请求简单数据
- 网络请求 Get & Post 方法(整理)
- php发送get、post请求的6种方法简明总结
- php使用fsockopen函数发送post,get请求获取网页内容的方法
- PHP + MySql + Stored Procedures, how do I get access an "out" value?
- PHP使用http_build_query()构造URL字符串的方法(可将POST参数组转换拼接成GET请求链接)
- PHP中使用cURL实现Get和Post请求的方法