oauth1.a&2.0以get,head,post請求access_token[php]

來源:互聯網
上載者:User

 忽如一夜春風來,千萬開放平台開。然而開放平台不是開房平台,你需要先申請一個叫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請求的類,使用了一個工廠,方便調用不同的請求方式。

 

sender.php
<?phpabstract 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
<?phpclass 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
<?phpinclude_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
<?phpinclude_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;}}?>

 

--待續--

 

 

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.