- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一段 PHP 代码,用于向我的 Azure 存储帐户中的容器创建 Blob 存储 PUT 请求。经过大量修改后,我终于得到了正确的标题,一切都很好。不幸的是,我想在其中使用它的应用程序是用 Perl 编写的。所以我认为移植它是一个相对容易的任务。事实证明这比我预想的要困难。
我已经比较了 PHP 代码和 Perl 代码之间的所有内容(嗯,显然不是所有内容,否则会很奇怪),但仍然收到与 header 相关的身份验证错误。
PHP 脚本使用 Curl 发出用户代理请求。我在 Perl 安装中无法直接替换它。不确定如果没有 Net::Curl 的本地安装和 C 编译器,我能做些什么。 (也许我在那里遗漏了一些东西?)因为两个版本(PHP 和 Perl)之间的所有内容似乎都匹配,即消息、 key 、字符串的编码/解码版本、散列签名(我硬编码了两个实现之间的验证日期) ,我不知道还能尝试什么。这是第三天,我觉得我可能正在忙着解决这个小组已经解决的问题。
运行良好的 PHP 代码:
<?php
date_default_timezone_set ( 'GMT' );
$date = date ( "D, d M Y H:i:s T" );
$version = "2009-09-19";
$account_name = 'emiliolizardo';
$account_key = "uXwt+WJ14kkV6zDALOuiDCsJtqrGDMK7W5xtNhuXXUcsfP1HIC1s7IJ+PZS7dgyXPBufad46ncBSQQK5rNs6Qw==";
$container_name = 'containertest';
$blobname = "foobar.txt";
$fdata = file_get_contents('testfile.txt');
$utfStr = "PUT"
. "\n\n\n"
. strlen($fdata)
. "\n\n"
. "text/plain; charset=UTF-8"
. "\n\n\n\n\n\n\n"
. "x-ms-blob-type:BlockBlob"
. "\n"
. "x-ms-date:$date"
. "\n"
. "x-ms-version:$version"
. "\n"
. "/$account_name/$container_name/$blobname";
$utf8_encode_str = utf8_encode ( $utfStr );
echo "utfStr : " . $utfStr . "\n";
echo "utf8_encode_str:" . $utf8_encode_str . "\n";
$signature_str = base64_encode(hash_hmac('sha256', $utf8_encode_str, base64_decode($account_key), true));
echo "signature_str:" . $signature_str . "\n";
$header = array (
"x-ms-blob-type: BlockBlob",
"x-ms-date: " . $date,
"x-ms-version: " . $version,
"Authorization: SharedKey " . $account_name . ":" . $signature_str,
"Content-Type: text/plain; charset=UTF-8",
"Content-Length: " . strlen($fdata),
);
print_r($header);
$url="https://$account_name.blob.core.windows.net/$container_name/$blobname";
echo "url:" . $url . "\n";
# Check our variables
#echo "account_name: " . $account_name . "\n";
#echo "account_key : " . $account_key . "\n";
#echo "signature : " . $signature_str . "\n";
#echo "url : " . $url . "\n";
#var_dump($header);
# Execute curl commands to create container
$ch = curl_init ();
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, 'PUT' );
curl_setopt ($ch, CURLOPT_URL, $url );
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $fdata);
curl_setopt ($ch, CURLOPT_HEADER, True );
$result = curl_exec ( $ch );
还有 Perl 代码,它很接近,但缺少一些东西:
#!/usr/bin/perl
use strict;
use DateTime;
use DateTime::TimeZone;
use Data::Dumper;
use Encode qw(decode encode);
use MIME::Base64 qw( encode_base64 decode_base64 );
use Digest::SHA qw(hmac_sha256 hmac_sha256_base64);
use HTTP::Request;
use LWP::UserAgent;
my $account_name = "emiliolizardo";
my $account_key = "uXwt+WJ14kkV6zDALOuiDCsJtqrGDMK7W5xtNhuXXUcsfP1HIC1s7IJ+PZS7dgyXPBufad46ncBSQQK5rNs6Qw==";
my $container = 'containertest';
#my $file = 'YhJCUjrcEi0q.mp3';
my $file = 'testfile.txt';
# -----------------------------------------------------------
# --
# -----------------------------------------------------------
sub uploadblob {
my ($fname, $accname, $acckey, $cont) = @_;
my $date = `/bin/date -u +"%a, %d %b %Y %T GMT"`; chomp $date;
# my $date = 'Mon, 01 Jul 2019 13:14:43 GMT'; # -- JUST FOR TESTING
# my $version = "2018-03-28";
my $version = "2009-09-19"; # -- JUST FOR TESTING TO MIMIC PHP CODE
my ($blobname, $ctype);
for ($fname) {
/\.mp3$/i and do { $ctype = 'audio/mpeg'; last; };
/\.wav$/i and do { $ctype = 'audio/wav'; last; };
/\.txt$/i and do { $ctype = 'text/plain'; last; };
die "Failed to match an acceptable extension";
}
my $blobname = $fname;
open FILE, "< $fname" or die "Can't open file $fname for read: $!";
my $fdata = <FILE>;
close FILE;
my $fsize = -s $fname;
my $str = qq{PUT\n\n\n$fsize\n\n$ctype; charset=UTF-8\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:$date\nx-ms-version:$version\n/$accname/$cont/$blobname};
print "utfStr : $str\n";
my $message = encode("UTF-8", $str);
print "utf8_encode_str:$message\n";
my $secret = decode_base64($acckey);
my $signature_str = encode_base64( hmac_sha256($message, $secret) );
chomp $signature_str;
print "signature_str:$signature_str\n";
# while(length($digest) %4) { $digest .= '='; } # -- Is this necessary for the hmac_sha256 digest?
my $header = [
'x-ms-blob-type' => "BlockBlob",
'x-ms-date' => $date,
'x-ms-version' => $version,
'Authorization' => "SharedKey $accname:$signature_str",
'Content-Type' => "$ctype; charset=UTF-8",
'Content-Length' => $fsize
];
my $url = "https://$accname.blob.core.windows.net/$cont/$blobname";
print "url:$url\n";
sendPut($header,$url,$fdata);
}
# -----------------------------------------------------------
# --
# -----------------------------------------------------------
sub sendPut {
my ($header,$url,$data) = @_;
print "\n\nIn sendPut()\n\n\n==============================================\n\n\n";
my $r = HTTP::Request->new('POST', $url, $header, $data);
my $ua = LWP::UserAgent->new();
my $res = $ua->request($r);
print "res: ", Dumper $res, "\n";
}
uploadblob($file, $account_name, $account_key, $container);
错误消息给了我一个提示,可能是什么问题,但我不确定如何纠正它:内容长度 header 错误,已修复。这似乎是 LWP 现有的问题(或者是在 2006 年,这是我找到的引用文献)。
在使用 LWP 发送 HTTP::Request 对象之前,使用 Data::Dumper 查看它,对我来说看起来没问题。就像 PHP 请求对象一样。在某些时候,我会用 PHP 或 Node.js 或当前的东西重写老式 Perl 代码,但目前,我真的很想让它在 Perl 中工作。
预先感谢您的任何建议。如果我违反了任何礼节,我深表歉意 - 在这里仍然很新。
谢谢 - 安迪
这是来自 UserAgent-> 请求的完整响应:
Content-Length header value was wrong, fixed at /usr/share/perl5/vendor_perl/LWP/Protocol/http.pm line 189.
res: $VAR1 = bless( {
'_protocol' => 'HTTP/1.1',
'_content' => '<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:62589eac-301e-00bd-3e1e-30c15e000000
Time:2019-07-01T15:04:08.0485043Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request \'PUUgk2meSoiB9o+inlYomIq96Bf13IdAQoIZ4BSu4sE=\' is not the same as any computed signature. Server used following string to sign: \'POST
26
text/plain; charset=UTF-8
x-ms-blob-type:BlockBlob
x-ms-date:Mon, 01 Jul 2019 15:04:07 GMT
x-ms-version:2009-09-19
/emiliolizardo/containertest/testfile.txt\'.</AuthenticationErrorDetail></Error>',
'_rc' => '403',
'_headers' => bless( {
'client-response-num' => 1,
'date' => 'Mon, 01 Jul 2019 15:04:07 GMT',
'client-ssl-cert-issuer' => '/C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/OU=Microsoft IT/CN=Microsoft IT TLS CA 4',
'client-ssl-cipher' => 'ECDHE-RSA-AES256-GCM-SHA384',
'client-peer' => '52.239.177.68:443',
'content-length' => '723',
'client-date' => 'Mon, 01 Jul 2019 15:04:08 GMT',
'client-ssl-warning' => 'Peer certificate not verified',
'content-type' => 'application/xml',
'x-ms-request-id' => '62589eac-301e-00bd-3e1e-30c15e000000',
'client-ssl-cert-subject' => '/CN=*.blob.core.windows.net',
'server' => 'Microsoft-HTTPAPI/2.0',
'client-ssl-socket-class' => 'IO::Socket::SSL'
}, 'HTTP::Headers' ),
'_msg' => 'Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.',
'_request' => bless( {
'_content' => 'Test file for blob upload
',
'_uri' => bless( do{\(my $o = 'https://emiliolizardo.blob.core.windows.net/containertest/testfile.txt')}, 'URI::https' ),
'_headers' => bless( {
'user-agent' => 'libwww-perl/5.833',
'x-ms-date' => 'Mon, 01 Jul 2019 15:04:07 GMT',
'content-type' => 'text/plain; charset=UTF-8',
'x-ms-version' => '2009-09-19',
'x-ms-blob-type' => 'BlockBlob',
'content-length' => 28,
'authorization' => 'SharedKey emiliolizardo:PUUgk2meSoiB9o+inlYomIq96Bf13IdAQoIZ4BSu4sE='
}, 'HTTP::Headers' ),
'_method' => 'POST',
'_uri_canonical' => $VAR1->{'_request'}{'_uri'}
}, 'HTTP::Request' )
}, 'HTTP::Response' );
$VAR2 = '
';
最佳答案
已在评论中解决。 @Grinnz 和 @Guarav Mantri - 你们说得对。
我的测试文件中有第二行(一个我没有看到的点)。因此,从文件中读取一行,但使用 -s 计算整个文件大小将导致不匹配。现在内容长度已正确计算。
当签名哈希中使用 PUT 时,我在 HTTP::Request-new() 调用中盲目地键入“POST”。哎呀。
谢谢大家。不知道如何对两个回复进行投票,因为两个回复都有部分答案。
关于azure - 了解使用 Perl、HTTP、LWP 的授权 header 有什么问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56838147/
如果我的 Perl 程序使用 Perl 模块,它将如何确定在哪里可以找到包含模块代码的文件? 例如,如果程序包含: use MyModule1; # Example 1 us
我在一个文件中有一些不同格式的数字:8.3、0.001、9e-18。我正在寻找一种简单的方法来读取它们并存储它们而不会损失任何精度。这在 AWK 中很容易,但在 Perl 中是如何完成的呢?我只愿意使
我在一个文件中有一些不同格式的数字:8.3、0.001、9e-18。我正在寻找一种简单的方法来读取它们并存储它们而不会损失任何精度。这在 AWK 中很容易,但在 Perl 中是如何完成的呢?我只愿意使
我正在自学 Perl,并且在我的 Windows 8 64 位系统上安装了 Strawberry。 Strawberry 命令行似乎工作正常,我在 C 驱动器上的 Strawberry 文件夹中创建了
我在 Perl 模块 IO::Socket::SSL 中发现了一个错误,我可能会修复它,但是,我担心测试修复。我从 Debian 下载了源码包(因为我打算为它制作一个 Debian 包或补丁)并查看了
我有一个 perl 文件,它使用了两个 perl 模块 A.pm 和 B.pm。 但是在 B.pm 中我需要调用 A.pm 的子程序。即使我在 A.pm 中使用并尝试使用它,我仍然遇到未定义的错误。
有没有办法在 Perl 运行时加载整个模块?我原以为我用 autouse 找到了一个很好的解决方案,但以下代码无法编译: package tryAutouse2; use autouse 'tryAu
过去,我编写过许多 perl 模块,以及不止一些独立的 perl 程序,但我之前从未发布过多文件 perl 程序。 我有一个几乎处于 beta 阶段的 perl 程序,它将被开源发布。它需要一些数据文
我有 1 个 perl 脚本,我们在其中编写了几个子例程。例子: # Try_1.pl main(); sub main{ --- --- check(); } check { -- --} 现在,
似乎 CPAN 上的一些(很多?)模块部分是使用 XS 在 C 中实现的,如果需要,可以回退到纯 perl 实现。虽然这很聪明,但它显然会损害性能,我想知道它是否会发生,以便我可以解决问题。 有没有一
我对 perl 很陌生。我希望我可以从 perl 安装一些软件包,我这样做是这样的: perl -MCPAN -e 'install VM::EC2' 我猜它由于依赖而失败,它显示: Result:
给定一个 Perl 包 Foo.pm,例如 package Foo; use strict; sub bar { # some code here } sub baz { # more
我有一个用 Perl 编写的测试生成器。它生成连接到模拟器的测试。这些测试本身是用 Perl 编写的,并通过其 API 连接到模拟器。我希望生成的代码是人类可读的,这意味着我希望它能够正确缩进和格式化
我正在学习 Perl,非常新的用户。我可以知道这些 Perl 代码之间有什么区别吗? #!/usr/bin/perl & #!/usr/bin/perl -w 最佳答案 那不是 perl 代码,它是
我不认为这是一个重复的问题。这专门针对 Perl 模块附带的脚本。 通常,在安装多个 Perl 版本时,您可以将 perl 可执行文件标记为版本号 (perl5.32),这样它们就可以在 /whate
我有一个在文件中使用 Blowfish 加密的程序和第二个 perl 程序,它提示输入用于将其解密为字符串的密码,我希望不必将解密的源代码写入硬盘驱动器,尽管将它放在内存中并不是真正的问题,因为运行程
有没有人为 Perl 中的惰性求值列表找到了一个好的解决方案?我尝试了很多方法来改变类似的东西 for my $item ( map { ... } @list ) { } 进入懒惰的评估——例如,通
我安装了多个版本的 Perl。 我已经指定了要使用的版本。但是为了验证,我想从 .pl 脚本本身输出 Perl 的版本。 这可能吗? 在 Perl 脚本中解析“perl --version”的输出似乎
人们还经常问“我怎样才能编译 Perl?”而他们真正想要的是创建一个可以在机器上运行的可执行文件,即使他们没有安装 Perl。 我知道有几种解决方案: perl2exe靛蓝之星 它是商业的。我从未尝试
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 8年前关闭。 Improve this
我是一名优秀的程序员,十分优秀!