ASP.Net 中的 Amazon CloudFront 失效

Posted

技术标签:

【中文标题】ASP.Net 中的 Amazon CloudFront 失效【英文标题】:Amazon CloudFront invalidation in ASP.Net 【发布时间】:2011-04-07 15:53:31 【问题描述】:

我不确定如何使用 ASP.Net 向 Amazon CloudFront 发送请求以使对象无效。

详情在这里http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?Invalidation.html 但我不确定如何在 ASP.Net 中实现这一点...有人可以帮忙吗?

【问题讨论】:

【参考方案1】:

从最新版本的适用于 .NET 的 AWS 开发工具包 (1.5.8.0) 开始,接受的答案不再有效。这应该可以解决问题:

using Amazon;
using Amazon.CloudFront.Model;

...

var client = AWSClientFactory.CreateAmazonCloudFrontClient(accessKey, secretKey);
client.CreateInvalidation(new CreateInvalidationRequest 
    DistributionId = distributionID,
    InvalidationBatch = new InvalidationBatch 
        Paths = new Paths 
            Quantity = arrayofpaths.Length,
            Items = arrayofpaths.ToList()
        ,
        CallerReference = DateTime.Now.Ticks.ToString()
    
);

【讨论】:

+1 可以让事情保持最新状态(很遗憾我的答案不再是了 ;-)【参考方案2】:

得到它的工作,如果其他人觉得它有用,就在这里。

    public static void InvalidateContent(string distributionId, string fileName)
    
        string httpDate = Helpers.GetHttpDate();

        ASCIIEncoding encoding = new ASCIIEncoding();
        string postData = @"<InvalidationBatch>" +
                            "   <Path>/" + fileName + "</Path>" +
                            "   <CallerReference>" + httpDate + "</CallerReference>" +
                            "</InvalidationBatch>";
        byte[] data = encoding.GetBytes(postData);

        // Prepare web request...
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://cloudfront.amazonaws.com/2010-08-01/distribution/" + distributionId + "/invalidation");
        webRequest.Method = "POST";
        webRequest.ContentType = "text/xml";
        webRequest.Headers.Add("x-amz-date", httpDate);

        Encoding ae = new UTF8Encoding();
        HMACSHA1 signature = new HMACSHA1(ae.GetBytes(GlobalSettings.AWSSecretAccessKey.ToCharArray()));
        string b64 = Convert.ToBase64String(signature.ComputeHash(ae.GetBytes(webRequest.Headers["x-amz-date"].ToCharArray())));
        webRequest.Headers.Add(HttpRequestHeader.Authorization, "AWS" + " " + GlobalSettings.AWSAccessKeyId + ":" + b64);

        webRequest.ContentLength = data.Length;

        Stream newStream = webRequest.GetRequestStream();
        // Send the data.
        newStream.Write(data, 0, data.Length);
        newStream.Close();
    

    /// <summary>
    /// Gets a proper HTTP date
    /// </summary>
    public static string GetHttpDate()
    
        // Setting the Culture will ensure we get a proper HTTP Date.
        string date = System.DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH:mm:ss ", System.Globalization.CultureInfo.InvariantCulture) + "GMT";
        return date;
    

【讨论】:

顺便给你同样的日期格式DateTime.UtcNow.ToString("R");【参考方案3】:

这是上面的python版本,如果有人觉得有用的话

from datetime import datetime
import urllib2, base64, hmac, hashlib

def getHTTPDate():
    return datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S UTC")

def submitInvalidationRequest(fileName,distributionId):
    url = "https://cloudfront.amazonaws.com/2010-08-01/distribution/" + distributionId + "/invalidation"
    httpDate = getHTTPDate();
    postData = "<InvalidationBatch>" +"<Path>/" + fileName + "</Path>" +"<CallerReference>" + httpDate + "</CallerReference>" +"</InvalidationBatch>";
    sig = hmac.new(AWSSecretAccessKey, unicode(httpDate), hashlib.sha1)

    headers = "ContentType": "text/xml",
           "x-amz-date": httpDate,
           "Authorization":"AWS " + AWSAccessKeyId + ":" +  base64.b64encode( sig.digest() )

    req = urllib2.Request(url,postData,headers)
    return urllib2.urlopen(req).read()

【讨论】:

【参考方案4】:

使用AWSSDK .net api wrapper from amazon 使这项任务更加容易。

using Amazon.CloudFront.Model;

...

var client = Amazon.AWSClientFactory.CreateAmazonCloudFrontClient(ConfigurationManager.AppSettings["Aws.AccessKey"],
                                                              ConfigurationManager.AppSettings["Aws.SecretKey"]);
var request = new PostInvalidationRequest();
request.DistributionId = ConfigurationManager.AppSettings["Cdn.DistributionId"];
request.InvalidationBatch = new InvalidationBatch();
request.InvalidationBatch.CallerReference = new Guid().ToString();
request.InvalidationBatch.Paths = PathsInput.Text.Split(new[]'\n','\r',StringSplitOptions.RemoveEmptyEntries).ToList();
var response = client.PostInvalidation(request);

【讨论】:

从适用于 .NET 的 AWS 开发工具包(版本 1.5.8.0)的最新更新开始,这似乎不再有效。我正在寻找替代品并将其发布在这里,除非有人能打败我。 :)【参考方案5】:

这里是 perl:

use warnings;
use strict;
use HTTP::Date;
use Digest::SHA qw(hmac_sha1);
use LWP::UserAgent;
use MIME::Base64;
use Encode qw(encode_utf8);

@ARGV == 4 || die "usage: $0 url distribution_id accesskey secretkey\n";

my $invalid_url = $ARGV[0];
my $distribution_id = $ARGV[1];
my $accesskey = $ARGV[2];
my $secretkey = $ARGV[3];

my $url = "https://cloudfront.amazonaws.com/2010-11-01/distribution/$distribution_id/invalidation";
my $date = time2str;

my $post_data = <<HERE;
<?xml version="1.0" encoding="UTF-8"?>
<InvalidationBatch>
  <Path>$invalid_url</Path>
  <CallerReference>$date</CallerReference>
</InvalidationBatch>
HERE

my $sig = encode_base64(hmac_sha1(encode_utf8($date),encode_utf8($secretkey)));

my $browser = LWP::UserAgent->new;
my $res = $browser->post($url,
                         "Content" => $post_data,
                         "ContentType" => "text/xml",
                         "x-amz-date" => $date,
                         "Authorization" => "AWS $accesskey:$sig");

print $res->status_line, "\n", $res->content;

【讨论】:

他没有要求 perl,是吗? ^^ Rob:他也没有要求 Python(作者 Alex Hofsteede),是吗?

以上是关于ASP.Net 中的 Amazon CloudFront 失效的主要内容,如果未能解决你的问题,请参考以下文章

如何在 asp.net mvc 中显示来自 Amazon S3 的图像文件?

asp.net core系列 69 Amazon S3 资源文件上传示例

在ECS中使用哪个ASP.NET Windows容器映像?使用Amazon ECS在基本映像中出现Windows Docker Container兼容性问题

Amazon S3 中的 403 禁止问题

在 Elastic Beanstalk 上的 Asp.net core 3.0

ASP.NET Web API