PHP的oAuth签名创建问题(将照片集发布到Tumblr)
我做了一个简单的脚本,在tumblr上发布图像.
一切都很好,但在我改变主机提供商(我的新主机有限且更便宜)后,我发现了一些性能问题. 现在,在调试脚本并联系tumblr api帮助台后,我遇到了一个问题: 有3个功能: function oauth_gen($method,$url,$iparams,&$headers) { $iparams['oauth_consumer_key'] = CONSUMER_KEY; $iparams['oauth_nonce'] = strval(time()); $iparams['oauth_signature_method'] = 'HMAC-SHA1'; $iparams['oauth_timestamp'] = strval(time()); $iparams['oauth_token'] = OAUTH_TOKEN; $iparams['oauth_version'] = '1.0'; $iparams['oauth_signature'] = oauth_sig($method,$iparams); $oauth_header = array(); foreach($iparams as $key => $value) { if (strpos($key,"oauth") !== false) { $oauth_header []= $key ."=".$value; } } $str = print_r($iparams,true); file_put_contents('data1-1.txt',$str); $oauth_header = "OAuth ". implode(",",$oauth_header); $headers["Authorization"] = $oauth_header; } function oauth_sig($method,$uri,$params) { $parts []= $method; $parts []= rawurlencode($uri); $iparams = array(); ksort($params); foreach($params as $key => $data) { if(is_array($data)) { $count = 0; foreach($data as $val) { $n = $key . "[". $count . "]"; $iparams []= $n . "=" . rawurlencode($val); //$iparams []= $n . "=" . $val; $count++; } } else { $iparams[]= rawurlencode($key) . "=" .rawurlencode($data); } } //debug($iparams,"iparams"); $str = print_r($iparams,true); file_put_contents('data-1.txt',$str); //$size = filesize('data.txt'); $parts []= rawurlencode(implode("&",$iparams)); //debug($parts,"parts"); //die(); $sig = implode("&",$parts); return base64_encode(hash_hmac('sha1',$sig,CONSUMER_SECRET."&". OAUTH_SECRET,true)); } 上面这两个函数来自一个在线功能实例,它们一直运行良好. 这是我用来调用API和oAuth的函数: function posta_array($files,$queue,$tags,$caption,$link,$blog){ $datArr = array(); $photoset_layout = ""; foreach ($files as $sing_file){ $dataArr [] = file_get_contents($sing_file); $photoset_layout .= "1"; } $headers = array("Host" => "http://api.tumblr.com/","Content-type" => "application/x-www-form-urlencoded","Expect" => ""); $params = array( "data" => $dataArr,"type" => "photo","state" => $queue,"tags"=>$tags,"caption"=>$caption,"photoset_layout" => $photoset_layout,"link"=>str_replace("_","",$link) ); debug($headers,"head"); oauth_gen("POST","http://api.tumblr.com/v2/blog/$blog/post",$params,$headers); debug($headers,"head 2"); $ch = curl_init(); curl_setopt($ch,CURLOPT_USERAGENT,"Tumblr v1.0"); curl_setopt($ch,CURLOPT_URL,"http://api.tumblr.com/v2/blog/$blog/post"); curl_setopt($ch,CURLOPT_RETURNTRANSFER,1 ); curl_setopt($ch,CURLOPT_HTTPHEADER,array( "Authorization: " . $headers['Authorization'],"Content-type: " . $headers["Content-type"],"Expect: ") ); $params = http_build_query($params); $str = print_r($params,true); file_put_contents('data_curl1.txt',$str); curl_setopt($ch,CURLOPT_POST,1); curl_setopt($ch,CURLOPT_POSTFIELDS,$params); $response = curl_exec($ch); debug($response,"response"); return $response; } 这是一些有问题的功能,我试着解释一下: 我调用了oauth_gen将参数数组传递给它,oauth_gen创建了我后来在这里使用的oauth头:“授权:”. $头[ ‘授权’],. 正如我所说的,一切都运作顺利,直到我试图发布6个文件的gif photoset总共6Mb(tumblr允许每个文件2Mb和总共10Mb). PHP耗尽内存并返回错误,这里它开始我的调试,一段时间后我联系了tumblr api帮助台,他们以这种方式回答:
这改变了一切.直到现在,我将整个参数数组传递给oauth_gen,调用oauth_sig,将所有内容原始编码到数组中(包含gif文件的二进制字符串),大约1Mb的二进制文件的结果变为至少3Mb的rawurlencoded串. 这就是我有记忆问题的原因.很好,所以,正如帮助台所说,我已经用这种方式改变了对oauth_gen的调用: $new_array = array(); oauth_gen("POST",$new_array,$headers); 接缝合法我,我传递了一个新的数组到函数,然后函数生成oAuth,标题被传回,我可以将它们用于发布调用,结果是: {"meta":{"status":401,"msg":"Unauthorized"},"response":[]} 要求更多tumblr api帮助台只会导致更多链接到他们的文档和他们的“tumblr php客户端”,我无法使用,所以它不是一个选项. 有没有人有oAuth的经验,可以解释我做错了什么?据我所知,诀窍是oauth_sig创建的加密数据,但我无法弄清楚如何继续. 我真的很想了解oauth,但是我更多地了解它以及更多tumblr helpdsek接缝对我来说,但是……解决方案不起作用,只有当我让oauth函数加密整个数据数组时才有效(有了图像和一切)但我能理解这是错的……帮助我. 更新1 更新2
在花了几个小时进入问题,调试,检查tumblr api和api客户端,注册测试帐户并尝试发布一些图像.好消息是我最终想出了一个解决方案.它不仅仅使用原生CURL,您需要guzzle和OAuth库来签署请求.
Tumblr伙伴们对签署请求是正确的.您无需传递图像数据即可对请求进行签名.如果你查看他们的官方图书馆,你可以看到; https://github.com/tumblr/tumblr.php/blob/master/lib/Tumblr/API/RequestHandler.php#L85 我试图解决原生CURL库的问题,但不幸的是我没有成功,要么是以错误的方式签署请求,要么在请求标题,数据等中丢失了一些东西.我实际上不知道,Tumblr api真的很糟糕通知你你做错了什么. 所以我欺骗了一点,开始阅读Tumblr api客户端代码,我想出了一个解决方案. 在这里,我们首先需要两个包. $composer require "eher/oauth:1.0.*" $composer require "guzzle/guzzle:>=3.1.0,<4" 然后PHP代码,只需定义你的密钥,令牌,秘密等.然后它应该是好的去. 由于签名请求不包括图片数据,因此不超过内存限制.实际签署请求后,我们没有将文件的内容放入我们的post数据数组中.我们正在使用guzzle的addPostFiles方法,它负责POST请求的文件添加,为你做脏工作.这是我的结果; string(70)“{”meta“:{”status“:201,”msg“:”Created“},”response“:{”id“:143679527674}}” <?php ini_set('memory_limit','64M'); define("CONSUMER_KEY",""); define("CONSUMER_SECRET",""); define("OAUTH_TOKEN",""); define("OAUTH_SECRET",""); function request($options,$blog) { // Take off the data param,we'll add it back after signing $files = isset($options['data']) ? $options['data'] : false; unset($options['data']); $url = "https://api.tumblr.com/v2/blog/$blog/post"; $client = new GuzzleHttpClient(null,array( 'redirect.disable' => true )); $consumer = new EherOAuthConsumer(CONSUMER_KEY,CONSUMER_SECRET); $token = new EherOAuthToken(OAUTH_TOKEN,OAUTH_SECRET); $oauth = EherOAuthRequest::from_consumer_and_token( $consumer,$token,"POST",$options ); $oauth->sign_request(new EherOAuthHmacSha1(),$consumer,$token); $authHeader = $oauth->to_header(); $pieces = explode(' ',$authHeader,2); $authString = $pieces[1]; // POST requests get the params in the body,with the files added // and as multipart if appropriate /** @var GuzzleHttpMessageRequestInterface $request */ $request = $client->post($url,null,$options); $request->addHeader('Authorization',$authString); if ($files) { if (is_array($files)) { $collection = array(); foreach ($files as $idx => $f) { $collection["data[$idx]"] = $f; } $request->addPostFiles($collection); } else { $request->addPostFiles(array('data' => $files)); } } $request->setHeader('User-Agent','tumblr.php/0.1.2'); // Guzzle throws errors,but we collapse them and just grab the // response,since we deal with this at the TumblrClient level try { $response = $request->send(); } catch (GuzzleHttpExceptionBadResponseException $e) { $response = $request->getResponse(); } // Construct the object that the Client expects to see,and return it $obj = new stdClass; $obj->status = $response->getStatusCode(); $obj->body = $response->getBody(); $obj->headers = $response->getHeaders()->toArray(); return $obj; } $files = [ "/photo/1.jpg","/photo/2.jpg","/photo/3.png","/photo/4.jpg","/photo/1.jpg",]; $params = array( "type" => "photo","state" => "published","tags"=> [],"caption"=>"caption","https://stackoverflow.com/questions/36747697/oauth-signature-creation-issue-with-php-posting-photoset-to-tumblr"),"data" => $files,); $response = request($params,"blog-transparentcoffeebouquet.tumblr.com"); var_dump($response->body->__toString()); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |