一对一源码搭建,使用文件签名防止资源过度使用

发布来源:云豹科技
发布人:云豹科技
2022-06-02 10:07:05

在当前一对一源码搭建过程中,云存储因为存储量大、访问速度快、性价比高,成为文件存储的首选。除此之外,云存储为了避免资源文件被过度使用,在获取文件路径时,通过给文件生成签名的方式来进行验证,保证一对一源码文件的安全性。下面,我们就来介绍一下腾讯云存储的文件签名方法。

一、签名方法

namespace Qcloud\Cos;
 
use Psr\Http\Message\RequestInterface;
 
class Signature {
    // string: access key.
    private $accessKey;
 
    // string: secret key.
    private $secretKey;
 
    // array: cos config.
    private $options;
 
    public function __construct( $accessKey, $secretKey, $options, $token = null ) {
        $this->accessKey = $accessKey;
        $this->secretKey = $secretKey;
        $this->options = $options;
        $this->token = $token;
        $this->signHeader = [
            'cache-control',
            'content-disposition',
            'content-encoding',
            'content-length',
            'content-md5',
            'content-type',
            'expect',
            'expires',
            'host',
            'if-match',
            'if-modified-since',
            'if-none-match',
            'if-unmodified-since',
            'origin',
            'range',
            'response-cache-control',
            'response-content-disposition',
            'response-content-encoding',
            'response-content-language',
            'response-content-type',
            'response-expires',
            'transfer-encoding',
            'versionid',
        ];
        date_default_timezone_set( 'PRC' );
    }
 
    public function __destruct() {
    }
 
    public function needCheckHeader( $header ) {
        if ( startWith( $header, 'x-cos-' ) ) {
            return true;
        }
        if ( in_array( $header, $this->signHeader ) ) {
            return true;
        }
        return false;
    }
 
    public function signRequest( RequestInterface $request ) {
        $authorization = $this->createAuthorization( $request );
        return $request->withHeader( 'Authorization', $authorization );
    }
 
    public function createAuthorization( RequestInterface $request, $expires = '+30 minutes' ) {
        if ( is_null( $expires ) || !strtotime( $expires )) {
            $expires = '+30 minutes';
        }
        $signTime = ( string )( time() - 60 ) . ';' . ( string )( strtotime( $expires ) );
        $urlParamListArray = [];
        foreach ( explode( '&', $request->getUri()->getQuery() ) as $query ) {
            if (!empty($query)) {
                $tmpquery = explode( '=', $query );
                //为了保证CI的key中有=号的情况也能正常通过,ci在这层之前已经encode了,这里需要拆开重新encode,防止上方explode拆错
                $key = strtolower( rawurlencode(urldecode($tmpquery[0])) );
                if (count($tmpquery) >= 2) {
                    $value = $tmpquery[1];
                } else {
                    $value = "";
                }
                //host开关
                if (!$this->options['signHost'] && $key == 'host') {
                    continue;
                }
                $urlParamListArray[$key] = $key. '='. $value;
            }
        }
        ksort($urlParamListArray);
        $urlParamList = join(';', array_keys($urlParamListArray));
        $httpParameters = join('&', array_values($urlParamListArray));
 
        $headerListArray = [];
        foreach ( $request->getHeaders() as $key => $value ) {
            $key = strtolower( urlencode( $key ) );
            $value = rawurlencode( $value[0] );
            if ( !$this->options['signHost'] && $key == 'host' ) {
                continue;
            }
            if ( $this->needCheckHeader( $key ) ) {
                $headerListArray[$key] = $key. '='. $value;
            }
        }
        ksort($headerListArray);
        $headerList = join(';', array_keys($headerListArray));
        $httpHeaders = join('&', array_values($headerListArray));
        $httpString = strtolower( $request->getMethod() ) . "\n" . urldecode( $request->getUri()->getPath() ) . "\n" . $httpParameters.
        "\n". $httpHeaders. "\n";
        $sha1edHttpString = sha1( $httpString );
        $stringToSign = "sha1\n$signTime\n$sha1edHttpString\n";
        $signKey = hash_hmac( 'sha1', $signTime, trim($this->secretKey) );
        $signature = hash_hmac( 'sha1', $stringToSign, $signKey );
        $authorization = 'q-sign-algorithm=sha1&q-ak='. trim($this->accessKey) .
        "&q-sign-time=$signTime&q-key-time=$signTime&q-header-list=$headerList&q-url-param-list=$urlParamList&" .
        "q-signature=$signature";
        return $authorization;
    }
 
    public function createPresignedUrl( RequestInterface $request, $expires = '+30 minutes' ) {
        $authorization = $this->createAuthorization( $request, $expires);
        $uri = $request->getUri();
        $query = 'sign='.urlencode( $authorization ) . '&' . $uri->getQuery();
        if ( $this->token != null ) {
            $query = $query.'&x-cos-security-token='.$this->token;
        }
        $uri = $uri->withQuery( $query );
        return $uri;
    }
}

 一对一源码通过调用createPresignedUrl方法,传入请求文件名和签名有效时间,就可以返回签名字符串了。一对一源码开发搭建并不是简单的事,有感兴趣的朋友可以继续关注我们,了解更多开发相关知识。

声明:以上内容为云豹科技原创,未经作者本人同意,禁止转载,否则将追究相关法律责任www.yunbaokj.com

声明:
以上内容为云豹科技作者本人原创,未经作者本人同意,禁止转载,否则将追究相关法律责任
立即查看