Oauth1.a & 2.0 request access_token with get, head, post [php]

Source: Internet
Author: User
Tags url decode

Ten millions of open platforms are available in the spring breeze of the night. However, the open platform is not an open data center platform. You need to apply for an item named access_token first. This is a three-party contract between your applications on the open platform (consumer), the open platform, and customers who use your applications to access their own data; the contract states that this user allows consumer to access the data of this user on the data center opening platform. Every time the consumer takes this contract to the data center opening platform, he can obtain the desired data.

There are two common methods to obtain access token: oauth1.a and oauth2.0 (oauth1.0 already exists and will be discarded due to security issues ). Before the process starts, you must apply for a consumer_key for your application (secret will be attached to any applied key and token, and secret will be useless in 2.0). consumer_key is used for application, consumer_secret + the secret attached to other tokens is used to extract the signature of Transmission Parameters and verify the correctness.

Oauth1.a is a complicated authentication process. It must first use consumer_key to apply for an unauthorized request token. After the user is authorized, it becomes an authorized request token and generates a verified callback address sent to the application in get mode (no callback address is ood, will send a pin code to the browser), and then the application will send the authorized request_token (in fact, the same as the unauthorized, so there is no new secret in the previous step) + verified request access_token.
Then, when calling the api, You need to extract the access token + function parameter + (consumer_secret + access_secret) Signature and send it to the open platform to return the function result.

Oau2's 4-way application adopts https encryption, so you do not need to manually extract the signature, and the authentication steps are simplified, so it is much simpler. In addition, the returned results are usually returned in json format. I will not explain it here.

HTTP request data can be stored in multiple ways. The Open Platform accepts three types of data: Post, get, head. Post. Put the data in the HTTP Request body. Get puts the request data in the URL and the URL? Split. If the head request is not to put the request in the head, the experiment shows that the method is get. The specific experiment is written later. Because get concatenates all the data to the URL in almost plain text, post and head are relatively secure. Therefore, post is recommended when sending some sensitive data.

========================================================== ===== Annoying theory till now ================================== ====================================

When oauth1.a & 2.0 requests Token, you need to send multiple HTTP requests. Some requests require browser redirection. Therefore, we first encapsulate various classes for sending HTTP requests and use a factory to call different request methods.

 

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 class; Signature Class:

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;}}?>

 

-- To be continued --

 

 

 

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.