举个栗子

马辰龙De技术分享
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

perl版阿里云签名公共参数方法

Posted on 2016-07-08 21:54  ChenlongMa  阅读(454)  评论(0编辑  收藏  举报

阿里云的签名验证真心蛋疼,比如时间戳做了二次utf8转码,文档中的签名结果与实际不相符等.

package AliYun;
use Moose;
use Redis;
use POSIX qw(strftime);
use Data::Dumper;
use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
use JSON;
use URI::Escape;
use LWP::UserAgent;
 
#定义签名常量
has 'accessKeyId'     => ( isa => 'Str', is => 'ro', required => 1 );
has 'accessKeySecret' => ( isa => 'Str', is => 'ro', required => 1 );
has 'format' =>
    ( isa => 'Str', is => 'rw', required => 1, default => 'json' );
has 'signatureMethod' =>
    ( isa => 'Str', is => 'rw', required => 1, default => 'HMAC-SHA1' );
has 'signatureVersion' =>
    ( isa => 'Str', is => 'rw', required => 1, default => '1.0' );
has 'serverUrl' => ( isa => 'Str', is => 'rw', required => 1 );
has 'version' =>
    ( isa => 'Str', is => 'rw', required => 1, default => '2015-01-09' );
has 'requestMethod' =>
    ( isa => 'Str', is => 'rw', required => 1, default => 'GET' );
 
has 'timestamp' => (
    isa      => 'Str',
    is       => 'rw',
    required => 1,
    default  => strftime( "%Y-%m-%dT%H:%M:%SZ", localtime( time - 3600 * 8 ) )
);
 
 
 
sub params_init {
    my $self = shift;
    my ($actionParams) = @_;
    my $apiParams;
    
#公共参数
    $apiParams->{AccessKeyId}      = $self->accessKeyId;
    $apiParams->{SignatureMethod}  = $self->signatureMethod;
    $apiParams->{SignatureVersion} = $self->signatureVersion;
    $apiParams->{TimeStamp}        = $self->timestamp;
    $apiParams->{SignatureNonce}   = rand;
    $apiParams->{Version}          = $self->version;
    $apiParams->{Format}           = $self->format;
 
    
#请求参数与公共参数合并
    $apiParams->{$_} = $actionParams->{$_} for keys %$actionParams;
 
    $apiParams->{Signature} = $self->compute_signature($apiParams);
 
    my $requestUrl = $self->serverUrl . "?";
    for my $key ( keys %$apiParams ) {
        my $value = uri_escape_utf8 $apiParams->{$key};
        $requestUrl .= "$key=" . $value . "&";
    }
 
    
#删除最后一个字符&
    $requestUrl = substr( $requestUrl, 0, -1 );
    my $ua     = LWP::UserAgent->new();
    my $result = $ua->get($requestUrl);
 
    return decode_json $result->content;
 
}
 
sub compute_signature {
    my ( $self, $paramData ) = @_;
    my $accessKeySecret = $self->accessKeySecret;
    my $canonicalizedQueryString;
    my $strArr;
    for my $key ( sort keys %$paramData ) {
        push @$strArr,
            uri_escape_utf8($key) . "="
            . uri_escape_utf8( $paramData->{$key} );
    }
    $canonicalizedQueryString = join "&", @$strArr;
 
    
# 生成用于计算签名的字符串 stringToSign
 
    my $stringToSign
        = 'GET&%2F&' . uri_escape_utf8($canonicalizedQueryString);
 
    
# 计算签名,注意accessKeySecret后面要加上字符'&'
    my $hmac = Digest::HMAC_SHA1->new( $accessKeySecret . "&" );
    $hmac->add($stringToSign);
    my $signStr = $hmac->b64digest;
    $signStr =~ s/$/=/g;
    return $signStr;
}
1;