百度智能云 API鉴权总结

最近在研究百度云的一些服务,处理api接口鉴权时花了不少时间,总结一下,方便大家对接:

  1. Signer.php:签名工具类,鉴权签名的核心方法都在这里
  2. Utils.php:封装的工具类,鉴权,返回json数据等都在这里
  3. Account.php:示例Controller,请求百度云接口

使用的tp5框架,代码仅供参考,思路可以供大家借鉴,如有不当之处,欢迎指正

签名工具类

Signer.php

/**  * Created by PhpStorm.  * User: 王中阳  * Date: 2021/3/07  * Time: 9:45  */   <?php  class SignerException extends Exception {     function __construct($message)     {         parent::__construct($message, 999);     } }  class Signer {     private $ak;     private $sk;     private $version = "1";     private $timestamp;     private $expiration = 1800;     private $method;     private $uri;     private $params = array();     private $headers = array();     private $needLog = false;      function __construct($accessKey, $secretKey)     {         $this->ak = $accessKey;         $this->sk = $secretKey;         $date = new DateTime('now');         $date->setTimezone(new DateTimeZone('UTC'));         $this->timestamp = $date->format('Y-m-dTH:i:sZ');     }      public function setVersion($version)     {         $this->version = $version;     }      public function setExpiration($expiration)     {         $this->expiration = $expiration;     }      public function setMethod($method)     {         if (!empty($method)) {             $this->method = strtoupper($method);         }     }      public function setTimestamp($timestamp)     {         $this->timestamp = $timestamp;     }      public function setUri($uri)     {         $this->uri = $uri;     }      public function setParams($params)     {         $this->params = $this->normalizeParam($params);     }      public function setSignHeaders($headers)     {         $this->headers = $this->normalizeHeaders($headers);     }      public function beLog($needLog)     {         $this->needLog = $needLog;     }      public function genAuthorization()     {         $signature = $this->genSignature();         $authStr = "bce-auth-v" . $this->version . "/" .             $this->ak . "/" . $this->timestamp . "/" .             $this->expiration . "/" . $this->getSignedHeaderNames() . "/" . $signature;         return $authStr;     }      public function genSignature()     {         if (empty($this->method)) {             throw new SignerException("method is null or empty");         }         $signingKey = $this->genSigningKey();         $this->signerLog("signingKey:" . $signingKey, __LINE__, __FILE__);         $authStr = $this->method . "n" .             $this->getCanonicalURI() . "n" .             $this->getCanonicalParam() . "n" .             $this->getCanonicalHeaders();         $this->signerLog("auth str:" . $authStr, __LINE__, __FILE__);         return $this->sha256($signingKey, $authStr);     }      public function genSigningKey()     {         if (empty($this->ak)) {             throw new SignerException("access key is null or empty");         }         if (empty($this->sk)) {             throw new SignerException("secret key is null or empty");         }         if (empty($this->version)) {             throw new SignerException("version is null or empty");         }         if (empty($this->timestamp)) {             throw new SignerException("timestamp is null or empty");         }         if (empty($this->expiration)) {             throw new SignerException("expiration is null or empty");         }         $authStr = "bce-auth-v" . $this->version . "/" . $this->ak . "/" .             $this->timestamp . "/" . $this->expiration;         return $this->sha256($this->sk, $authStr);     }      public function getCanonicalParam()     {         if (empty($this->params)) {             return "";         }         $arryLen = count($this->params);         $canonicalParams = "";         foreach ($this->params as $key => $value) {             if (is_array($value)) {                 $num = count($value);                 if (count($value) == 0) {                     $canonicalParams = $canonicalParams . $key . "=";                 } else {                     foreach ($value as $item) {                         $canonicalParams = $canonicalParams . $key . "=" . $item;                         if ($num > 1) {                             $canonicalParams = $canonicalParams . "&";                             $num--;                         }                     }                 }             } else {                 $canonicalParams = $canonicalParams . $key . "=" . $value;             }             if ($arryLen > 1) {                 $canonicalParams = $canonicalParams . "&";                 $arryLen--;             }         }         return $canonicalParams;     }      public function getCanonicalURI()     {         if (empty($this->uri)) {             throw new SignerException("uri is null or empty");         }         $newUri = $this->dataEncode($this->uri, true);         if (strpos($newUri, "/") === 0) {             return $newUri;         }         return "/" . $newUri;     }      public function getCanonicalHeaders()     {         if (empty($this->headers) || !array_key_exists("host", $this->headers)) {             throw new SignerException("host not in headers");         }         $canonicalHeaders = "";         $strArry = array();         foreach ($this->headers as $key => $value) {             if (empty($value)) {                 continue;             }             $strArry[] = $this->dataEncode($key, false) . ":" . $value;         }         $arryLen = count($strArry);         for ($i = 0; $i < $arryLen; $i++) {             if ($i < $arryLen - 1) {                 $canonicalHeaders = $canonicalHeaders . $strArry[$i] . "n";                 continue;             }             $canonicalHeaders = $canonicalHeaders . $strArry[$i];         }         return $canonicalHeaders;     }      private function sha256($key, $data)     {         return hash_hmac('sha256', $data, $key);     }      private function dataEncode($data, $isPath)     {         if (empty($data)) {             return "";         }         $encode = mb_detect_encoding($data, array("ASCII", "UTF-8", "GB2312", "GBK", "BIG5"));         if ($encode != "UTF-8") {             $data = $code1 = mb_convert_encoding($data, 'utf-8', $encode);         }         $encodeStr = rawurlencode($data);         if ($isPath) {             $encodeStr = str_replace("%2F", "/", $encodeStr);         }         return $encodeStr;     }      private function normalizeHeaders($headers)     {         $newArray = array();         if (empty($headers)) {             return $newArray;         }         foreach ($headers as $key => $value) {             $newKey = strtolower($key);             if (empty($newKey)) {                 continue;             }             $newArray[$newKey] = $this->dataEncode(trim($value), false);         }         ksort($newArray);         return $newArray;     }      private function normalizeParam($params)     {         $newArray = array();         if (empty($params)) {             return $newArray;         }         foreach ($params as $key => $value) {             if (empty($key) || strtolower($key) == "authorization") {                 continue;             }             if (is_array($value)) {                 $newSubArray = array();                 foreach ($value as $item) {                     $newSubArray[] = $this->dataEncode($item, false);                 }                 sort($newSubArray);                 $newArray[$this->dataEncode($key, false)] = $newSubArray;             } else {                 $newArray[$this->dataEncode($key, false)] = $this->dataEncode($value, false);             }         }         ksort($newArray);         return $newArray;     }      private function getSignedHeaderNames()     {         $arryLen = count($this->headers);         $headerNames = "";         foreach ($this->headers as $key => $value) {             $headerNames = $headerNames . $key;             if ($arryLen > 1) {                 $headerNames = $headerNames . ";";                 $arryLen--;             }         }         return $headerNames;     }      private function signerLog($content, $line, $file)     {         if ($this->needLog) {             error_log($file . ":" . $line . ":[" . $content . "]n", 3, "./signer_log");         }     } }  ?> 

封装的工具类,集成了常用的方法

Utils.php

<?php  /**  * Created by PhpStorm.  * User: 王中阳  * Date: 2021/3/07  * Time: 9:45  */ require 'Signer.php'; define('AK', "your ak"); define('SK', "your sk"); define('HOST', "sem.baidubce.com"); //按百度要求换内容 define('BASE_URL', "http://sem.baidubce.com/");//按百度要求换内容 define('HTTP_Method', "POST");//按百度要求换内容  class Utils {     //公共header  注意:我对接的是百度信息流推广api,header应根据百度云各服务的要求进行修改     static function Header()     {         return [             'opUsername' => 'xxxxxxx',             'opPassword' => 'xxxxxxx',             'tgUsername' => 'xxxxxxx',             'tgPassword' => 'xxxxxxx',             'bceUser' => 'xxxxxxx',         ];     }      //请求百度     static function curl_post($url, $body, $auth)     {         //处理请求体         $files = [             'header' => self::Header(),             'body' => $body         ];         $files = json_encode($files, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);          $ch = curl_init();         curl_setopt($ch, CURLOPT_POST, 1);         curl_setopt($ch, CURLOPT_URL, $url);           curl_setopt($ch, CURLOPT_POSTFIELDS, $files);         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);         curl_setopt($ch, CURLOPT_HTTPHEADER, array(                 'Content-Type: application/json',                 'host:sem.baidubce.com',  //改成你的数据                 'authorization:' . $auth,                 'accept-encoding:gzip, deflate',                 'accept:*/*'             )         );         $response = curl_exec($ch);         $request = curl_getinfo($ch, CURLINFO_HEADER_OUT);         $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);         self::result($httpCode, $response);     }      //校验权限     static function gen_auth($uri = "")     {         $headers = array();         $headers['host'] = HOST;         $signer = new Signer(AK, SK);         $signer->setMethod(HTTP_Method);         $signer->setUri($uri);         $signer->setSignHeaders($headers);         try {             $signature = $signer->genAuthorization();             return $signature;         } catch (SignerException $e) {             echo $e->getMessage();             return;         }     }      //返回结果     static public function result($errno = 0, $data = '')     {         header("Content-type: application/json;charset=utf-8");          $errno = intval($errno);          //注意:这里可能不满足你的项目 根据百度返回结果做修改 或者不用我这种处理方式         //json转数组         $data = json_decode($data, true);         if (isset($data['header']['failures'][0])) {             $message = $data['header']['failures'][0]['message'];         } else {             $message = 'success';         }          $json = json_encode($data['body']['data'][0]);         $result = array(             'errno' => 1,             'message' => $message,             'data' => json_encode($data['body']['data'][0]),//处理百度 返回结果         );         echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);         exit;     }      /**      * 时间 日期      */     static public function ymd($time)     {         return date("Y-m-d", $time);     } } 

业务层controller:百度api在请求接口的同时做权限校验

Account.php

/**  * Created by PhpStorm.  * User: 王中阳  * Date: 2021/3/07  * Time: 9:45  */   <?php namespace appindexcontroller;  require 'Utils.php';  class Account {     /**      * 获得账号信息      */     public function info()     {         $uri = "v1/feed/cloud/AccountFeedService/getAccountFeed";         $auth = Utils::gen_auth($uri);         $url = BASE_URL . $uri;          $body = [             'accountFeedFields' => [                 'userId',                 'balance',                 'budget',                 'balancePackage',                 'userStat',                 'uaStatus',                 'validFlows',             ],         ];         //返回数据集成在Utils中         Utils::curl_post($url, $body, $auth);     } 

思路仅供参考。如有更好的处理方式,欢迎赐教。

版权声明:玥玥 发表于 2021-03-09 8:18:08。
转载请注明:百度智能云 API鉴权总结 | 女黑客导航