162 lines
4.0 KiB
PHP
162 lines
4.0 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
namespace AlibabaCloud\Credentials\Providers;
|
|||
|
|
|
|||
|
|
use AlibabaCloud\Credentials\Credential\RefreshResult;
|
|||
|
|
|
|||
|
|
abstract class SessionCredentialsProvider implements CredentialsProvider
|
|||
|
|
{
|
|||
|
|
/**
|
|||
|
|
* @var array
|
|||
|
|
*/
|
|||
|
|
protected static $credentialsCache = [];
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Expiration time slot for temporary security credentials.
|
|||
|
|
*
|
|||
|
|
* @var int
|
|||
|
|
*/
|
|||
|
|
protected $expirationSlot = 180;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @var string
|
|||
|
|
*/
|
|||
|
|
protected $error = 'Result contains no credentials';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Get the credentials from the cache in the validity period.
|
|||
|
|
*
|
|||
|
|
* @return RefreshResult|null
|
|||
|
|
*/
|
|||
|
|
protected function getCredentialsInCache()
|
|||
|
|
{
|
|||
|
|
if (isset(self::$credentialsCache[$this->key()])) {
|
|||
|
|
$result = self::$credentialsCache[$this->key()];
|
|||
|
|
return $result;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Cache credentials.
|
|||
|
|
*
|
|||
|
|
* @param RefreshResult $credential
|
|||
|
|
*/
|
|||
|
|
protected function cache(RefreshResult $credential)
|
|||
|
|
{
|
|||
|
|
self::$credentialsCache[$this->key()] = $credential;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Get credential.
|
|||
|
|
*
|
|||
|
|
* @return Credentials
|
|||
|
|
*/
|
|||
|
|
public function getCredentials()
|
|||
|
|
{
|
|||
|
|
if ($this->cacheIsStale() || $this->shouldInitiateCachePrefetch()) {
|
|||
|
|
$result = $this->refreshCache();
|
|||
|
|
$this->cache($result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
$result = $this->getCredentialsInCache();
|
|||
|
|
|
|||
|
|
return $result->credentials();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @return RefreshResult
|
|||
|
|
*/
|
|||
|
|
protected function refreshCache()
|
|||
|
|
{
|
|||
|
|
try {
|
|||
|
|
return $this->handleFetchedSuccess($this->refreshCredentials());
|
|||
|
|
} catch (\Exception $e) {
|
|||
|
|
return $this->handleFetchedFailure($e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @return RefreshResult
|
|||
|
|
* @throws \Exception
|
|||
|
|
*/
|
|||
|
|
protected function handleFetchedFailure(\Exception $e)
|
|||
|
|
{
|
|||
|
|
$currentCachedValue = $this->getCredentialsInCache();
|
|||
|
|
if (is_null($currentCachedValue)) {
|
|||
|
|
throw $e;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (time() < $currentCachedValue->staleTime()) {
|
|||
|
|
return $currentCachedValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
throw $e;
|
|||
|
|
}
|
|||
|
|
/**
|
|||
|
|
* @return RefreshResult
|
|||
|
|
*/
|
|||
|
|
protected function handleFetchedSuccess(RefreshResult $value)
|
|||
|
|
{
|
|||
|
|
$now = time();
|
|||
|
|
// 过期时间大于15分钟,不用管
|
|||
|
|
if ($now < $value->staleTime()) {
|
|||
|
|
return $value;
|
|||
|
|
}
|
|||
|
|
// 不足或等于15分钟,但未过期,下次会再次刷新
|
|||
|
|
if ($now < $value->staleTime() + 15 * 60) {
|
|||
|
|
$value->staleTime = $now;
|
|||
|
|
return $value;
|
|||
|
|
}
|
|||
|
|
// 已过期,看缓存,缓存若大于15分钟,返回缓存,若小于15分钟,则稍后重试
|
|||
|
|
if (is_null($this->getCredentialsInCache())) {
|
|||
|
|
throw new \Exception("The fetched credentials have expired and no cache is available.");
|
|||
|
|
} else if ($now < $this->getCredentialsInCache()->staleTime()) {
|
|||
|
|
return $this->getCredentialsInCache();
|
|||
|
|
} else {
|
|||
|
|
// 返回成功,延长有效期 1 分钟
|
|||
|
|
$expectation = mt_rand(50, 70);
|
|||
|
|
$value->staleTime = time() + $expectation;
|
|||
|
|
return $value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @return bool
|
|||
|
|
*/
|
|||
|
|
protected function cacheIsStale()
|
|||
|
|
{
|
|||
|
|
return is_null($this->getCredentialsInCache()) || time() >= $this->getCredentialsInCache()->staleTime();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @return bool
|
|||
|
|
*/
|
|||
|
|
protected function shouldInitiateCachePrefetch()
|
|||
|
|
{
|
|||
|
|
return is_null($this->getCredentialsInCache()) || time() >= $this->getCredentialsInCache()->prefetchTime();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @return int
|
|||
|
|
*/
|
|||
|
|
public function getStaleTime($expiration)
|
|||
|
|
{
|
|||
|
|
return $expiration <= 0 ?
|
|||
|
|
time() + (60 * 60) :
|
|||
|
|
$expiration - (15 * 60);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @return RefreshResult
|
|||
|
|
*/
|
|||
|
|
abstract function refreshCredentials();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Get the toString of the credentials provider as the key.
|
|||
|
|
*
|
|||
|
|
* @return string
|
|||
|
|
*/
|
|||
|
|
abstract function key();
|
|||
|
|
}
|