通过自定义网站重定向Amazon AWS访问的选项

时间:2017-01-17 19:10:07

标签: c# amazon-web-services

我们开发了一个利用Amazon AWS S3 SDK客户端从AWS桶获取对象(文件)的应用程序。该平台将要求系统能够访问s3.amazonaws.com。但是,我们的一些客户不想打开防火墙到amazon.com(当进入s3.amazonaws.com到网络浏览器时,它会重定向到aws.amazon.com/s3)。我们如何使用自己的域名站点重定向到Amazon AWS站点,并能够使用SDK for .NET获取对象(文件)?

谢谢, 宝林

2 个答案:

答案 0 :(得分:0)

您可以使用CNAME来识别Host:标头,但除非您设置了反向代理,否则您的客户端仍然必须允许其防火墙访问。见Customizing Amazon S3 URLs with CNAMEs

如果您希望所有客户端访问权限都通过您控制的IP地址,则可以使用反向代理。有很多关于为这个特定用例设置一个的教程:

您也可以在应用内代理请求。例如,使用MVC Core,Microsoft.AspNetCore.Proxy middleware允许您设置传递给第三方的路由。

取自Joseph Woodward's网站的示例:

// Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    ...

    app.MapWhen(IsAdminPath, builder => builder.RunProxy(new ProxyOptions
    {
        Scheme = "http",
        Host = "localhost",
        Port = "8081"
    }));

    ...

}

private static bool IsAdminPath(HttpContext httpContext)
{
    return httpContext.Request.Path.Value.StartsWith(@"/admin/", StringComparison.OrdinalIgnoreCase);
}

要使用Windows服务创建代理,您可以使用WCF:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract(Namespace = ServiceNamespace)]
[DataContractFormat]
public class FileContentService : IFileContentService, INullContract
{
    public FileContentService()
    {
        client = new AmazonS3Client(Amazon.RegionalEndpoint.USEast1);
    }

    [OperationContract, WebGet(UriTemplate = "Files/{fileId}")]
    public io.Stream GetFileContent(string fileId)
    {
        GetObjectRequest request = new GetObjectRequest 
        {
            BucketName = bucketName,
            Key = fileId
        };

        var response = client.GetObject(request);
        // copy relevant headers (MIME, ETag, Cache-Control, etc...)
        // WebOperationContext.Current.OutgoingResponse.SetETag(etag);
        // WebOperationContext.Current.OutgoingResponse.ContentType = foo;
        // WebOperationContext.Current.OutgoingResponse.Headers
        //     .Add(HttpResponseHeader.CacheControl, "{cache options}");
        return response.ResponseStream;
    }
}

public class FileContentServiceManager : IDisposable
{
    private ServiceHost shThis;

    public FileContentServiceManager()
    {
        shThis = new ServiceHost(typeof(FileContentService), new Uri("https://localhost/foo/bar"));
        shThis.AddServiceEndpoint(typeof(FileContentService), GetBinding(), "")
            .Behaviors.Add(new WebHttpBehavior());
        shThis.Open();
    }

    public void Dispose()
    {
        shThis.Close();
    }

    static Binding GetBinding()
    {
        var b = new WebHttpBinding();
        b.MaxReceivedMessageSize = 28 * 1024 * 1024 * 2;
        b.ReaderQuotas.MaxBytesPerRead = 4096 * 1024;
        b.ReaderQuotas.MaxDepth = 32;
        b.ReaderQuotas.MaxStringContentLength = 4096 * 1024;
        b.ReaderQuotas.MaxArrayLength = 4096 * 1024;
        b.Security.Mode = WebHttpSecurityMode.Transport;

        CustomBinding result = new CustomBinding(b);
        WebMessageEncodingBindingElement webMEBE = result.Elements.Find<WebMessageEncodingBindingElement>();
        webMEBE.ContentTypeMapper = new MyMapper();

        return result;
    }

    class MyMapper : WebContentTypeMapper
    {
        public override WebContentFormat GetMessageFormatForContentType(string contentType)
        {
            return WebContentFormat.Raw; // always
        }
    }
}

答案 1 :(得分:0)

最终我们使用了不同的方式来解决这个问题:我们在 URL 中添加了更具体的前缀以缩小对亚马逊网站的访问范围。 AWS 的命名约定要求前缀使用“-”而不是“.”。例如:我们需要使用“myproduct-bucket.s3.amazonaws.com”而不是“myproduct.bucket.s3.amamzonaws.com”。