Amazon AWS S3浏览器在PHP上上传(AWS签名版本4)

时间:2022-11-19 09:36:29

There seems to be something wrong with this documentation: http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html

这个文档似乎有问题:http://docs.aws.amazon.com/amazons3/latest/api/sigv4身份验证——httppost .html

I followed it exactly and it does seem to work. I always got SignatureDoesNotMatch error. v2 authorization works though. Makes me wonder if this some kind of Alpha-stage quality product.

我确实遵循了它,而且它似乎确实有效。我总是有签名不匹配的错误。v2授权作品。这让我怀疑这是不是某种一流的产品。

Below is my php code. I tried to mimic the example in this page: http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html

下面是我的php代码。我尝试模仿这个页面中的示例:http://docs.aws.amazon.com/amazons3/latest/api/sigv4 post-example.html

<?php

$secret = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY';

$datenow = '20130806';
$region = 'us-east-1';
$service = 's3';
$terminator = 'aws4_request';
$policy = '{ "expiration": "2013-08-07T12:00:00.000Z",
  "conditions": [
    {"bucket": "examplebucket"},
    ["starts-with", "$key", "user/user1/"],
    {"acl": "public-read"},
    {"success_action_redirect": "http://examplebucket.s3.amazonaws.com/successful_upload.html"},
    ["starts-with", "$Content-Type", "image/"],
    {"x-amz-meta-uuid": "14365123651274"},
    ["starts-with", "$x-amz-meta-tag", ""],

    {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/'.$datenow.'/'.$region.'/'.$service.'/'.$terminator.'"},
    {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
    {"x-amz-date": "'.$datenow.'T000000Z" }
  ]
}';

$policy64 = base64_encode($policy);

assert($policy64 == $policy64);
$targetPolicy64 = 'eyAiZXhwaXJhdGlvbiI6ICIyMDEzLTA4LTA3VDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJleGFtcGxlYnVja2V0In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIka2V5IiwgInVzZXIvdXNlcjEvIl0sDQogICAgeyJhY2wiOiAicHVibGljLXJlYWQifSwNCiAgICB7InN1Y2Nlc3NfYWN0aW9uX3JlZGlyZWN0IjogImh0dHA6Ly9leGFtcGxlYnVja2V0LnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRtbCJ9LA0KICAgIFsic3RhcnRzLXdpdGgiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS8iXSwNCiAgICB7IngtYW16LW1ldGEtdXVpZCI6ICIxNDM2NTEyMzY1MTI3NCJ9LA0KICAgIFsic3RhcnRzLXdpdGgiLCAiJHgtYW16LW1ldGEtdGFnIiwgIiJdLA0KDQogICAgeyJ4LWFtei1jcmVkZW50aWFsIjogIkFLSUFJT1NGT0ROTjdFWEFNUExFLzIwMTMwODA2L3VzLWVhc3QtMS9zMy9hd3M0X3JlcXVlc3QifSwNCiAgICB7IngtYW16LWFsZ29yaXRobSI6ICJBV1M0LUhNQUMtU0hBMjU2In0sDQogICAgeyJ4LWFtei1kYXRlIjogIjIwMTMwODA2VDAwMDAwMFoiIH0NCiAgXQ0KfQ==';
// echo base64_decode($targetPolicy64);
// echo $policy64."\n".$targetPolicy64;

assert($policy64 == $targetPolicy64);

// At this point everything seems to work well. Converting the policy 
// to base64 resulted in exactly the same string with example. 
// The problem, however, happens when calculating the signature, 
// as shown below:

$targetSignature = '21496b44de44ccb73d545f1a995c68214c9cb0d41c45a17a5daeec0b1a6db047';
$signature = '';

$hash1 = hash_hmac(
    'sha256',
    $datenow,
    "AWS4".$secret,
    true
);

$hash2 = hash_hmac(
    'sha256',
    $region,
    $hash1,
    true
);

$hash3 = hash_hmac(
    'sha256',
    $service,
    $hash2,
    true
);

$signingKey = hash_hmac(
    'sha256',
    $terminator,
    $hash3,
    true
);

$signature = base64_encode(hash_hmac(
    'sha256',
    $policy64,
    $signingKey,
    true
));


echo $signature."\n".$targetSignature;
// This assertion never passed.
assert($signature == $targetSignature);

I thought it was the problem of the example so I tried creating a sample browser upload page with exactly the same methods, but it did not work either.

我认为这是示例的问题,所以我尝试使用完全相同的方法创建一个示例浏览器上传页面,但它也不起作用。

Running the signature signing code here: PHP hash_hmac not matching AWS Signature 4 example however, works, so I doubt the issue is during signature creation, or is it?

在这里运行签名代码:PHP hash_hmac不匹配AWS签名4示例,但是,可以工作,所以我怀疑问题是在签名创建过程中,还是在创建过程中?

Please help, anyone.

请帮助,任何人。

1 个解决方案

#1


-1  

<?php

// Fill These In!
define('S3_BUCKET', '');
define('S3_KEY',    '');
define('S3_SECRET', '');
define('S3_REGION', '');        // S3 region name: http://amzn.to/1FtPG6r
define('S3_ACL',    'private'); // File permissions: http://amzn.to/18s9Gv7
// Stop Here

$algorithm = "AWS4-HMAC-SHA256";
$service = "s3";
$date = gmdate('Ymd\THis\Z');
$shortDate = gmdate('Ymd');
$requestType = "aws4_request";
$expires = '86400'; // 24 Hours
$successStatus = '201';

$scope = [
    S3_KEY,
    $shortDate,
    S3_REGION,
    $service,
    $requestType
];
$credentials = implode('/', $scope);

$policy = [
    'expiration' => gmdate('Y-m-d\TG:i:s\Z', strtotime('+6 hours')),
    'conditions' => [
        ['bucket' => S3_BUCKET],
        ['acl' => S3_ACL],
        [
            'starts-with',
            '$key',
            ''
        ],
        ['success_action_status' => $successStatus],
        ['x-amz-credential' => $credentials],
        ['x-amz-algorithm' => $algorithm],
        ['x-amz-date' => $date],
        ['x-amz-expires' => $expires],
    ]
];
$base64Policy = base64_encode(json_encode($policy));

// Signing Keys
$dateKey = hash_hmac('sha256', $shortDate, 'AWS4' . S3_SECRET, true);
$dateRegionKey = hash_hmac('sha256', S3_REGION, $dateKey, true);
$dateRegionServiceKey = hash_hmac('sha256', $service, $dateRegionKey, true);
$signingKey = hash_hmac('sha256', $requestType, $dateRegionServiceKey, true);

// Signature
$signature = hash_hmac('sha256', $base64Policy, $signingKey);

?>

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Direct Upload Example</title>
        <style>
            .progress {
                position: relative;
                width: 100%;
                height: 15px;
                background: #C7DA9F;
                border-radius: 10px;
                overflow: hidden;
            }
            .bar {
                position: absolute;
                top: 0; left: 0;
                width: 0; height: 15px;
                background: #85C220;
            }
            .bar.red { background: tomato; }
        </style>
    </head>
    <body>

        <!-- Direct Upload to S3 -->
        <!-- URL prefix (//) means either HTTP or HTTPS (depending on which is being currently used) -->
        <form action="//<?php echo S3_BUCKET . "." . $service . "-" . S3_REGION; ?>.amazonaws.com"
              method="POST"
              enctype="multipart/form-data"
              class="direct-upload">

            <!-- Note: Order of these is Important -->
            <input type="hidden" name="key" value="${filename}">
            <input type="hidden" name="acl" value="<?php echo S3_ACL; ?>">
            <input type="hidden" name="success_action_status" value="<?php echo $successStatus; ?>">
            <input type="hidden" name="policy" value="<?php echo $base64Policy; ?>">

            <input type="hidden" name="X-amz-algorithm" value="<?php echo $algorithm; ?>">
            <input type="hidden" name="X-amz-credential" value="<?php echo $credentials; ?>">
            <input type="hidden" name="X-amz-date" value="<?php echo $date; ?>">
            <input type="hidden" name="X-amz-expires" value="<?php echo $expires; ?>">
            <input type="hidden" name="X-amz-signature" value="<?php echo $signature; ?>">

            <input type="file" name="file">

            <!-- Progress Bar to show upload completion percentage -->
            <div class="progress"><div class="bar"></div></div>

        </form>

        <!-- Used to Track Upload within our App -->
        <form action="server.php" method="POST">
            <input type="hidden" name="upload_original_name" id="upload_original_name">
            <label for="upload_custom_name">Name:</label><br />
            <input type="text" name="upload_custom_name" id="upload_custom_name"><br />
            <input type="submit" value="Save"/>
        </form>

        <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
        <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
        <script src="fileupload/jquery.fileupload.js"></script>
        <script>
            $(document).ready(function () {
                $('.direct-upload').each(function () {
                    var form = $(this);
                    form.fileupload({
                        url: form.attr('action'),
                        type: 'POST',
                        datatype: 'xml',
                        add: function (event, data) {

                            // Message on unLoad.
                            // Shows 'Are you sure you want to leave message', just to confirm.
                            window.onbeforeunload = function () {
                                return 'You have unsaved changes.';
                            };

                            // Actually submit to form, sending the data.
                            data.submit();
                        },
                        progress: function (e, data) {
                            // This is what makes everything really cool, thanks to that callback
                            // you can now update the progress bar based on the upload progress.
                            var percent = Math.round((data.loaded / data.total) * 100);
                            $('.bar').css('width', percent + '%');
                        },
                        fail: function (e, data) {
                            // Remove the 'unsaved changes' message.
                            window.onbeforeunload = null;
                            $('.bar').css('width', '100%').addClass('red');
                        },
                        done: function (event, data) {
                            window.onbeforeunload = null;
                            // Fill the name field with the file's name.
                            $('#upload_original_name').val(data.originalFiles[0].name);
                            $('#upload_custom_name').val(data.originalFiles[0].name);
                        }
                    });
                });
            });
        </script>
    </body>
</html>

(https://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/)

(https://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/)

Works for me

适合我

#1


-1  

<?php

// Fill These In!
define('S3_BUCKET', '');
define('S3_KEY',    '');
define('S3_SECRET', '');
define('S3_REGION', '');        // S3 region name: http://amzn.to/1FtPG6r
define('S3_ACL',    'private'); // File permissions: http://amzn.to/18s9Gv7
// Stop Here

$algorithm = "AWS4-HMAC-SHA256";
$service = "s3";
$date = gmdate('Ymd\THis\Z');
$shortDate = gmdate('Ymd');
$requestType = "aws4_request";
$expires = '86400'; // 24 Hours
$successStatus = '201';

$scope = [
    S3_KEY,
    $shortDate,
    S3_REGION,
    $service,
    $requestType
];
$credentials = implode('/', $scope);

$policy = [
    'expiration' => gmdate('Y-m-d\TG:i:s\Z', strtotime('+6 hours')),
    'conditions' => [
        ['bucket' => S3_BUCKET],
        ['acl' => S3_ACL],
        [
            'starts-with',
            '$key',
            ''
        ],
        ['success_action_status' => $successStatus],
        ['x-amz-credential' => $credentials],
        ['x-amz-algorithm' => $algorithm],
        ['x-amz-date' => $date],
        ['x-amz-expires' => $expires],
    ]
];
$base64Policy = base64_encode(json_encode($policy));

// Signing Keys
$dateKey = hash_hmac('sha256', $shortDate, 'AWS4' . S3_SECRET, true);
$dateRegionKey = hash_hmac('sha256', S3_REGION, $dateKey, true);
$dateRegionServiceKey = hash_hmac('sha256', $service, $dateRegionKey, true);
$signingKey = hash_hmac('sha256', $requestType, $dateRegionServiceKey, true);

// Signature
$signature = hash_hmac('sha256', $base64Policy, $signingKey);

?>

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Direct Upload Example</title>
        <style>
            .progress {
                position: relative;
                width: 100%;
                height: 15px;
                background: #C7DA9F;
                border-radius: 10px;
                overflow: hidden;
            }
            .bar {
                position: absolute;
                top: 0; left: 0;
                width: 0; height: 15px;
                background: #85C220;
            }
            .bar.red { background: tomato; }
        </style>
    </head>
    <body>

        <!-- Direct Upload to S3 -->
        <!-- URL prefix (//) means either HTTP or HTTPS (depending on which is being currently used) -->
        <form action="//<?php echo S3_BUCKET . "." . $service . "-" . S3_REGION; ?>.amazonaws.com"
              method="POST"
              enctype="multipart/form-data"
              class="direct-upload">

            <!-- Note: Order of these is Important -->
            <input type="hidden" name="key" value="${filename}">
            <input type="hidden" name="acl" value="<?php echo S3_ACL; ?>">
            <input type="hidden" name="success_action_status" value="<?php echo $successStatus; ?>">
            <input type="hidden" name="policy" value="<?php echo $base64Policy; ?>">

            <input type="hidden" name="X-amz-algorithm" value="<?php echo $algorithm; ?>">
            <input type="hidden" name="X-amz-credential" value="<?php echo $credentials; ?>">
            <input type="hidden" name="X-amz-date" value="<?php echo $date; ?>">
            <input type="hidden" name="X-amz-expires" value="<?php echo $expires; ?>">
            <input type="hidden" name="X-amz-signature" value="<?php echo $signature; ?>">

            <input type="file" name="file">

            <!-- Progress Bar to show upload completion percentage -->
            <div class="progress"><div class="bar"></div></div>

        </form>

        <!-- Used to Track Upload within our App -->
        <form action="server.php" method="POST">
            <input type="hidden" name="upload_original_name" id="upload_original_name">
            <label for="upload_custom_name">Name:</label><br />
            <input type="text" name="upload_custom_name" id="upload_custom_name"><br />
            <input type="submit" value="Save"/>
        </form>

        <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
        <script src="//code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
        <script src="fileupload/jquery.fileupload.js"></script>
        <script>
            $(document).ready(function () {
                $('.direct-upload').each(function () {
                    var form = $(this);
                    form.fileupload({
                        url: form.attr('action'),
                        type: 'POST',
                        datatype: 'xml',
                        add: function (event, data) {

                            // Message on unLoad.
                            // Shows 'Are you sure you want to leave message', just to confirm.
                            window.onbeforeunload = function () {
                                return 'You have unsaved changes.';
                            };

                            // Actually submit to form, sending the data.
                            data.submit();
                        },
                        progress: function (e, data) {
                            // This is what makes everything really cool, thanks to that callback
                            // you can now update the progress bar based on the upload progress.
                            var percent = Math.round((data.loaded / data.total) * 100);
                            $('.bar').css('width', percent + '%');
                        },
                        fail: function (e, data) {
                            // Remove the 'unsaved changes' message.
                            window.onbeforeunload = null;
                            $('.bar').css('width', '100%').addClass('red');
                        },
                        done: function (event, data) {
                            window.onbeforeunload = null;
                            // Fill the name field with the file's name.
                            $('#upload_original_name').val(data.originalFiles[0].name);
                            $('#upload_custom_name').val(data.originalFiles[0].name);
                        }
                    });
                });
            });
        </script>
    </body>
</html>

(https://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/)

(https://www.designedbyaturtle.co.uk/2015/direct-upload-to-s3-using-aws-signature-v4-php/)

Works for me

适合我