Example #1
0
 /**
  * Sign the given request with the given set of credentials. Modifies the passed-in request to apply the signature.
  *
  * @param $credentials array the credentials to sign the request with.
  * @param $httpMethod string
  * @param $path string
  * @param $headers array
  * @param $params array
  * @param $options  array   the options for signing.
  * @return string The signed authorization string.
  */
 public function sign(array $credentials, $httpMethod, $path, $headers, $params, $options = array())
 {
     if (!isset($options[SignOptions::EXPIRATION_IN_SECONDS])) {
         $expirationInSeconds = SignOptions::DEFAULT_EXPIRATION_IN_SECONDS;
     } else {
         $expirationInSeconds = $options[SignOptions::EXPIRATION_IN_SECONDS];
     }
     $accessKeyId = $credentials['ak'];
     $secretAccessKey = $credentials['sk'];
     if (isset($options[SignOptions::TIMESTAMP])) {
         $timestamp = $options[SignOptions::TIMESTAMP];
     } else {
         $timestamp = new \DateTime();
     }
     $timestamp->setTimezone(DateUtils::$UTC_TIMEZONE);
     $authString = BceV1Signer::BCE_AUTH_VERSION . '/' . $accessKeyId . '/' . DateUtils::formatAlternateIso8601Date($timestamp) . '/' . $expirationInSeconds;
     $signingKey = hash_hmac('sha256', $authString, $secretAccessKey);
     // Formatting the URL with signing protocol.
     $canonicalURI = BceV1Signer::getCanonicalURIPath($path);
     // Formatting the query string with signing protocol.
     $canonicalQueryString = HttpUtils::getCanonicalQueryString($params, true);
     // Sorted the headers should be signed from the request.
     $headersToSign = null;
     if (isset($options[SignOptions::HEADERS_TO_SIGN])) {
         $headersToSign = $options[SignOptions::HEADERS_TO_SIGN];
     }
     // Formatting the headers from the request based on signing protocol.
     $canonicalHeader = BceV1Signer::getCanonicalHeaders(BceV1Signer::getHeadersToSign($headers, $headersToSign));
     $signedHeaders = '';
     if ($headersToSign !== null) {
         $signedHeaders = strtolower(trim(implode(";", array_keys($headersToSign))));
     }
     $canonicalRequest = "{$httpMethod}\n{$canonicalURI}\n" . "{$canonicalQueryString}\n{$canonicalHeader}";
     // Signing the canonical request using key with sha-256 algorithm.
     $signature = hash_hmac('sha256', $canonicalRequest, $signingKey);
     $authorizationHeader = "{$authString}/{$signedHeaders}/{$signature}";
     return $authorizationHeader;
 }
Example #2
0
 /**
  * Get a session with token in push/play url.
  *
  * More specifically, if the security policy used by this session enables push/play auth,
  * its push/play url need be updated with a token parameter computed from the session id,
  * the session stream, etc., and the security policy auth key. This function returns the
  * detailed session info with push/play url updated, if necessary.
  *
  * @param $sessionId string, session id
  * @param int $expireInMinute number, the push/play url expire time in minute
  * @param array $options Supported options:
  *      {
  *          config: the optional bce configuration, which will overwrite the
  *                  default client configuration that was passed in constructor.
  *      }
  * @return mixed
  * @throws BceClientException
  */
 public function getSessionWithToken($sessionId, $expireInMinute = 120, $options = array())
 {
     $session = $this->getSession($sessionId, $options);
     $securityPolicy = $this->getSecurityPolicy($session->securityPolicy);
     $currentTime = new \DateTime();
     $expireTime = $currentTime->add(new \DateInterval("PT{$expireInMinute}M"));
     $expireTime->setTimezone(DateUtils::$UTC_TIMEZONE);
     $expireString = DateUtils::formatAlternateIso8601Date($expireTime);
     if ($securityPolicy->auth->play) {
         if (isset($session->play->hlsUrl)) {
             $hlsUrl = $session->play->hlsUrl;
             $hlsTokenPlain = '/' . $sessionId . '/live.m3u8;' . $expireString;
             $hlsToken = hash_hmac('sha256', $hlsTokenPlain, $securityPolicy->auth->key);
             $session->play->hlsUrl = $hlsUrl . '?token=' . $hlsToken . '&expire=' . $expireString;
         } elseif (isset($session->play->hlsUrls)) {
             $hlsUrls = array();
             foreach ($session->play->hlsUrls as $line => $hlsUrl) {
                 if (isset($hlsUrl)) {
                     $hlsToken = '';
                     if ($line == 'L0') {
                         $hlsTokenPlain = '/' . $sessionId . '/live.m3u8;' . $expireString;
                         $hlsToken = hash_hmac('sha256', $hlsTokenPlain, $securityPolicy->auth->key);
                     } else {
                         $hlsTokenPlain = '/' . $sessionId . '-' . $line . '/live.m3u8;' . $expireString;
                         $hlsToken = hash_hmac('sha256', $hlsTokenPlain, $securityPolicy->auth->key);
                     }
                     $hlsUrls[$line] = $hlsUrl . '?token=' . $hlsToken . '&expire=' . $expireString;
                 }
             }
             $session->play->hlsUrls = $hlsUrls;
         }
         if (isset($session->play->rtmpUrl)) {
             $rtmpUrls = array();
             $rtmpUrl = $session->play->rtmpUrl;
             $rtmpTokenPlain = $sessionId . ';' . $expireString;
             $rtmpToken = hash_hmac('sha256', $rtmpTokenPlain, $securityPolicy->auth->key);
             $session->play->rtmpUrl = $rtmpUrl . '?token=' . $rtmpToken . '&expire=' . $expireString;
         } elseif (isset($session->play->rtmpUrls)) {
             foreach ($session->play->rtmpUrls as $line => $rtmpUrl) {
                 if (isset($rtmpUrl)) {
                     $rtmpTokenPlain = $sessionId . ';' . $expireString;
                     $rtmpToken = hash_hmac('sha256', $rtmpTokenPlain, $securityPolicy->auth->key);
                     $rtmpUrls[$line] = $rtmpUrl . '?token=' . $rtmpToken . '&expire=' . $expireString;
                 }
             }
             $session->play->rtmpUrls = $rtmpUrls;
         }
         if (isset($session->play->flvUrl)) {
             $flvUrl = $session->play->flvUrl;
             $flvTokenPlain = $sessionId . ';' . $expireString;
             $flvToken = hash_hmac('sha256', $flvTokenPlain, $securityPolicy->auth->key);
             $session->play->flvUrl = $flvUrl . '?token=' . $flvToken . '&expire=' . $expireString;
         } elseif (isset($session->play->flvUrls)) {
             $flvUrls = array();
             foreach ($session->play->flvUrls as $line => $flvUrl) {
                 if (isset($flvUrl)) {
                     $flvTokenPlain = $sessionId . ';' . $expireString;
                     $flvToken = hash_hmac('sha256', $flvTokenPlain, $securityPolicy->auth->key);
                     $flvUrls[$line] = $flvUrl . '?token=' . $flvToken . '&expire=' . $expireString;
                 }
             }
             $session->play->flvUrls = $flvUrls;
         }
     }
     if ($securityPolicy->auth->push) {
         if (isset($session->publish->pushUrl)) {
             $pushUrl = $session->publish->pushUrl;
             $pushTokenPlain = $session->publish->pushStream . ';' . $expireString;
             $pushToken = hash_hmac('sha256', $pushTokenPlain, $securityPolicy->auth->key);
             $session->publish->pushUrl = $pushUrl . '?token=' . $pushToken . '&expire=' . $expireString;
         }
     }
     return $session;
 }
Example #3
0
 /**
  * Send request to BCE.
  *
  * @param array $config
  * @param string $httpMethod The Http request method, uppercase.
  * @param string $path The resource path.
  * @param string|resource $body The Http request body.
  * @param array $headers The extra Http request headers.
  * @param array $params The extra Http url query strings.
  * @param SignerInterface $signer This function will generate authorization header.
  * @param resource|string $outputStream Write the Http response to this stream.
  *
  * @return \Guzzle\Http\Message\Response body and http_headers
  *
  * @throws BceClientException
  * @throws BceServiceException
  */
 public function sendRequest(array $config, $httpMethod, $path, $body, array $headers, array $params, SignerInterface $signer, $outputStream = null, $options = array())
 {
     $headers[HttpHeaders::USER_AGENT] = sprintf('bce-sdk-php/%s/%s/%s', Bce::SDK_VERSION, php_uname(), phpversion());
     if (!isset($headers[HttpHeaders::BCE_DATE])) {
         $now = new \DateTime();
         $now->setTimezone(DateUtils::$UTC_TIMEZONE);
         $headers[HttpHeaders::BCE_DATE] = DateUtils::formatAlternateIso8601Date($now);
     }
     list($hostUrl, $hostHeader) = HttpUtils::parseEndpointFromConfig($config);
     $headers[HttpHeaders::HOST] = $hostHeader;
     $url = $hostUrl . HttpUtils::urlEncodeExceptSlash($path);
     $queryString = HttpUtils::getCanonicalQueryString($params, false);
     if ($queryString !== '') {
         $url .= "?{$queryString}";
     }
     if (!isset($headers[HttpHeaders::CONTENT_LENGTH])) {
         $headers[HttpHeaders::CONTENT_LENGTH] = $this->guessContentLength($body);
     }
     $entityBody = null;
     if ($headers[HttpHeaders::CONTENT_LENGTH] == 0) {
         //if passing a stream and content length is 0, guzzle will remove
         //"Content-Length:0" from header, to work around this, we have to
         //set body to a empty string
         $entityBody = "";
     } else {
         if (is_resource($body)) {
             $offset = ftell($body);
             $original = EntityBody::factory($body);
             $entityBody = new ReadLimitEntityBody($original, $headers[HttpHeaders::CONTENT_LENGTH], $offset);
         } else {
             $entityBody = $body;
         }
     }
     $headers[HttpHeaders::AUTHORIZATION] = $signer->sign($config[BceClientConfigOptions::CREDENTIALS], $httpMethod, $path, $headers, $params, $options);
     if (LogFactory::isDebugEnabled()) {
         $this->logger->debug('HTTP method: ' . $httpMethod);
         $this->logger->debug('HTTP url: ' . $url);
         $this->logger->debug('HTTP headers: ' . print_r($headers, true));
     }
     $guzzleRequestOptions = array('exceptions' => false);
     if (isset($config[BceClientConfigOptions::CONNECTION_TIMEOUT_IN_MILLIS])) {
         $guzzleRequestOptions['connect_timeout'] = $config[BceClientConfigOptions::CONNECTION_TIMEOUT_IN_MILLIS] / 1000.0;
     }
     if (isset($config[BceClientConfigOptions::SOCKET_TIMEOUT_IN_MILLIS])) {
         $guzzleRequestOptions['timeout'] = $config[BceClientConfigOptions::SOCKET_TIMEOUT_IN_MILLIS] / 1000.0;
     }
     $guzzleRequest = $this->guzzleClient->createRequest($httpMethod, $url, $headers, $entityBody, $guzzleRequestOptions);
     if ($outputStream !== null) {
         $guzzleRequest->setResponseBody($outputStream);
     }
     // Send request
     try {
         $guzzleResponse = $this->guzzleClient->send($guzzleRequest);
     } catch (\Exception $e) {
         throw new BceClientException($e->getMessage());
     }
     if ($guzzleResponse->isInformational()) {
         throw new BceClientException('Can not handle 1xx Http status code');
     } elseif (!$guzzleResponse->isSuccessful()) {
         $requestId = $guzzleResponse->getHeader(HttpHeaders::BCE_REQUEST_ID);
         $message = $guzzleResponse->getReasonPhrase();
         $code = null;
         if ($guzzleResponse->isContentType('json')) {
             try {
                 $responseBody = $guzzleResponse->json();
                 if (isset($responseBody['message'])) {
                     $message = $responseBody['message'];
                 }
                 if (isset($responseBody['code'])) {
                     $code = $responseBody['code'];
                 }
             } catch (\Exception $e) {
                 // ignore this error
                 $this->logger->warning('Fail to parse error response body: ' . $e->getMessage());
             }
         }
         throw new BceServiceException($requestId, $code, $message, $guzzleResponse->getStatusCode());
     }
     if ($outputStream === null) {
         $body = $guzzleResponse->getBody(true);
     } else {
         $body = null;
         // detach the stream so that it will not be closed when the response
         // is garbage collected.
         $guzzleResponse->getBody()->detachStream();
     }
     return array('headers' => $this->parseHeaders($guzzleResponse), 'body' => $body);
 }