首页 > 其他分享 >Net Core项目通过Amazon SDK访问天翼云对象存储服务OOS问题

Net Core项目通过Amazon SDK访问天翼云对象存储服务OOS问题

时间:2023-02-10 23:55:05浏览次数:62  
标签:Core cn 天翼云 认证 Amazon OOS SDK

Net Core项目通过Amazon SDK访问天翼云对象存储服务OOS问题 

背景

近期在阿里云运营的Net Core项目应客户要求需要部署到天翼云,其中比较麻烦的事情是把阿里云对象存储服务OSS改为天翼云对象存储服务OOS,搞了3天,折腾个半死,好不容易才搞定了,赶紧记录下来。

天翼云的对象存储服务有3种,经典I型,经典II型,融合版。我的项目需求比较简单,就是一些数据文件不适合存数据库的,就用OSS存起来,一般的OSS都能用。简单对比了一下,发现经典I型,经典II型都没有.Net的SDK,融合版有.Net的SDK,为了方便快速开发就用融合版吧。然后在创建融合版的存储桶的时候,提示已售完,晕死。

发个了工单问客服,推荐我用经典I型,就这么办吧。在经典I型开通OOS,创建桶,购买资源包,创建访问Key备用。

 

第一关:通过Web Api访问天翼云OOS拼接认证头签名不对

学习天翼云通过Web Api访问OOS的文档,比如PUT上传一个文件,结构是简单的

https://www.ctyun.cn/document/10026693/10027315

 

但是,Authorization需要根据上传内容动态拼接出来,非常复杂,看得我头顶冒青烟。

https://www.ctyun.cn/document/10026693/10027058

验证码计算方法如下:

 

"Authorization: AWS" + AccessId + ":" + Signature

Signature =Base64( HMAC-SHA1( YourSecretAccessKey, UTF-8-Encoding-Of( StringToSign ) ) ) ;

StringToSign = HTTP-VERB + "\n" +

Content-MD5 + "\n" +

Content-Type + "\n" +

Date + "\n" +

CanonicalizedAmzHeaders +"\n" +

CanonicalizedResource;

 

CanonicalizedAmzHeaders = [详见下列描述];

CanonicalizedResource = [ "/" + Bucket ] +

<HTTP-Request-URI > +

  [<sub-resource>]

 

PUT Object

 

向名为johnsmith的bucket中上传一个对象。

请求

StringToSign

PUT /photos/puppy.jpg   HTTP/1.1

Content-Type:   image/jpeg

Content-Length: 94328

Host: johnsmith.oos-cn.ctyunapi.cn

Date: Tue, 27 Mar 2007   21:15:45 +0000

Authorization: AWS 7799e793ce4624ee7e5a:hcicpDDvL9SsO6AkvxqmIWkmOuQ=

PUT\n

\n

image/jpeg\n

Tue,   27 Mar 2007 21:15:45 +0000\n

/johnsmith/photos/puppy.jpg

注意:Content-Type请求头包含在请求中,也包含在StringToSign中。但请求中没有Content-MD5请求头,所以StringToSign中是空行。

 

也参考了天翼云OOS通过java创建认证头的例子。

https://www.ctyun.cn/document/10026693/10027543

 

我参考示例拼接认证头,试了很多次,都不成功。通过HttpClient发起调用,服务端总是返回403禁止访问错误,认证签名错误。

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>

 

在百度上找了很久,只找到一篇文章,作者做了一些封装,拼接认证头,成功访问了天翼云OOS。我用作者的方法,仍然无法解决认证签名错误的问题。

https://www.cnblogs.com/JackXiong/p/10875953.html

《_NET CORE 对接天翼云 OOS - 懒惰的jacky - 博客园.html》

 

第二关:通过Amazon SDK访问OOS认证头签名不对

Web Api这条路走不通,还有别的路可走吗?

再次学习天翼云OSS经典I型的资料,发现了一个重要信息:兼容Amazon S3标准!

https://www.ctyun.cn/document/10026693/10026712

天翼云对象存储(经典版)I型(Object-Oriented Storage,以下简称OOS)是中国电信为客户提供的一种海量、弹性、高可用、高性价比的对象存储服务。客户只需花极少的钱就可以获得一个几乎无限的存储空间,可以随时根据需要调整对资源的占用,并只需为真正使用的资源付费。OOS提供了基于Web门户和基于REST接口两种访问方式,用户可以在任何地方通过互联网对数据进行管理和访问。OOS提供的REST接口与Amazon S3兼容,因此基于OOS的业务可以非常轻松的与Amazon S3对接。用户还可以使用OOS提供迁移工具轻松地实现海量数据的移入与移出。

 

既然如此,那么客户端是不是可以通过Amazon S3的库,实现对天翼云OOS的访问呢?这样就不用自己拼接认证头了,SDK本来就干这个的啊!而且,在网上可以找到相当多的Amazon S3 Net core SDK访问云服务的资料,Amazon对.Net还是很友好的。天翼云OOS融合版也有.Net的SDK,经过仔细研究,它用的就是Amazon的SDK。

https://console.xstore.ctyun.cn/doc/store/sdk/dotnet/quickUse.html

安装SDK:

在天翼云官网下载,下载地址:OSS_DOTNET_SDK.zip

修改项目的csproj文件,在<PropertyGroup>中增加以下内容。

<PropertyGroup>

<RestoreSources>$(RestoreSources);filePathToPackage</RestoreSources>

</PropertyGroup>

其中filePathToPackage指的是OSS_DOTNET_SDK.zip解压后的径。然后在项目csproj文件所在目录下执行dotnet命令安装依赖包:

dotnet add package AWSSDK.S3 --version 3.7.0.18

# 使用sts服务需要添加以下依赖

dotnet add package AWSSDK.SecurityToken --version 3.7.1.6

dotnet restore

 

参考PUT上传对象的示例写代码即可,基本上照搬即可。

https://console.xstore.ctyun.cn/doc/store/sdk/dotnet/objectOperation/putObject.html

 

另外,天翼云官网OOS融合版也提供了.Net SDK源代码。

https://console.xstore.ctyun.cn/doc/store/sdk/introduction.html

去gitee下载它的代码学习一下。

https://gitee.com/ctyun-xstore/ctyun-xstore-sdk-demo

它里边有一段初始化代码可以借鉴一下

D:\software\test\ctyun-xstore-sdk-demo-master\oss-csharp-demo\oss-csharp-demo\S3Demo.cs

public S3Demo()
        {
            Amazon.AWSConfigs.LoggingConfig.LogTo = Amazon.LoggingOptions.Console;
            Amazon.AWSConfigs.LoggingConfig.LogResponses = Amazon.ResponseLoggingOption.Always;

            var credentials = new BasicAWSCredentials(Config.AccessKey, Config.SecretKey);
            var conf = new AmazonS3Config
            {
                ServiceURL = Config.EndPoint,
                AuthenticationRegion = "cn",
                Timeout = TimeSpan.FromSeconds(10),
                ReadWriteTimeout = TimeSpan.FromSeconds(10),
                RetryMode = RequestRetryMode.Standard,
                MaxErrorRetry = 2,
            };
            this.s3Client = new AmazonS3Client(credentials, conf);
        }

我参照以上示例写了测试DEMO,运行报错,还好错误提示很清晰,认证头的region期望是cn,实际上是us-east-1。但是我明明设置AuthenticationRegion = "cn"了,为什么没有生效呢?

<Error><Code>AuthorizationHeaderMalformed</Code><Message>The authorization header is malformed. the region 'us-east-1' is wrong; expecting 'cn'</Message>

通过Fiddler抓包也非常清晰的看到,认证头的region确实是us-east-1不对。

Authorization: AWS4-HMAC-SHA256 Credential=687e486556264706fbc7/20230210/us-east-1/s3/aws4_request, SignedHeaders=content-length;content-type;host;user-agent;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length, Signature=9b6...

多次检查后才发现,我的域名写错了,类似PUT http://bucketname.bucketname.oos-cn.ctyunapi.cn/test.obj HTTP/1.1,把路由修正之后,region问题解决了。

Authorization: AWS4-HMAC-SHA256 Credential=687e486556264706fbc7/20230210/cn/s3/aws4_request, SignedHeaders=content-length;content-type;host;user-agent;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length, Signature=590

但是访问天翼云OOS仍然返回SignatureDoesNotMatch认证签名不对!连SDK签名都不对,我还能怎么办?只好再给天翼云提工单。

 

第三关:设置了正确的region

天翼云的客服响应很快,经过和技术客服沟通,对方告知region必须设置为具体的地点,比如山东青岛sdqd,不能是cn,首先得修改OOS容器的区域设置,指定固定地点,不允许系统自动调度。

然后把访问OOS的EndPoint域名,认证region都改为sdgq,例如:

EndPoint=”https://oos-sdqd.ctyunapi.cn”

AuthenticationRegion = "sdqd"

 

再次测试,抓包看发送信息,域名,region都符合要求了。

PUT https://xxx.oos-sdqd.ctyunapi.cn/test.obj HTTP/1.1

Expect: 100-continue

User-Agent: aws-sdk-dotnet-coreclr/3.7.0.18 aws-sdk-dotnet-core/3.7.0.17 .NET_Core/7.0.1 OS/Microsoft_Windows_10.0.22000 ClientAsync

amz-sdk-invocation-id: e98f3de2-23ab-4cbb-8454-175b6015686d

amz-sdk-request: attempt=1; max=5

Host: xxx.oos-sdqd.ctyunapi.cn

X-Amz-Date: 20230210T073839Z

X-Amz-Decoded-Content-Length: 10240

X-Amz-Content-SHA256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD

Authorization: AWS4-HMAC-SHA256 Credential=687e486556264706fbc7/20230210/sdqd/s3/aws4_request, SignedHeaders=content-length;content-type;host;user-agent;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length, Signature=0dc...

traceparent: 00-74306b9e29bb01800d7ad7ff09bc293b-753f784ed4c13320-00

Content-Length: 10415

Content-Type: application/octet-stream

 

但是访问天翼云OOS仍然返回SignatureDoesNotMatch认证签名不对!

这次天翼云的技术客服也没招了,告知天翼云OOS不兼容Amazon S3的SDK。如果还想继续打通Amazon S3 SDK这条路,我只能靠自己了。

 

第四关:降级使用版本2认证头

百度,客服都无路可走了。折腾了这么久,元气已经耗尽了,头顶已经处于冒火状态。奥密克戎都没把我带走,这个难题差点要了我这半条老命。

冷静下来想了一下,还有活路。在VS2022的NuGet里边,搜索天翼云相关的库,勾选预览版,以关键字ctyun搜索,没有任何结果,真是绝了。

最后一条活路,在GitHub里边搜索ctyun,居然找到一个C# netcore的仓库!终于体验到“垂死病中惊坐起”的感觉。无比感谢大佬。

https://github.com/mn-s/ctyun-oos-net-core-sdk

 

我下载了代码,填上自己的天翼云OOS参数,运行一下PUT上传对象,居然成功了!卧槽!!最后一线希望居然成功了。

赶紧Fiddler抓包看发送的数据,原来用的是版本2的认证头!难怪了。

PUT https://xxx.oos-sdqd.ctyunapi.cn/test.obj HTTP/1.1

Host: xxx.oos-sdqd.ctyunapi.cn

Expect: 100-continue

User-Agent: aws-sdk-dotnet-coreclr/3.3.104.6 aws-sdk-dotnet-core/3.3.103.18 .NET_Core/7.0.1 OS/Microsoft_Windows_10.0.22000 ClientAsync

X-Amz-Date: Fri, 10 Feb 2023 09:31:49 GMT

Authorization: AWS 687e486556264706fbc7:AvJwhPrQ3B50IhrHMIsuXq62VNY=

Content-Length: 20

Content-Type: application/octet-stream

 

Ctyun OOS SDK for C#

 

HTTP/1.1 200 OK

Date: Fri, 10 Feb 2023 09:31:51 GMT

x-amz-request-id: 102c12aa50c34c8cb92c1f2e23303238f7f901edeff1f3f5f7

ETag: "847259bd5a9bb8fd1c13b17f1253229b"

Content-Length: 0

Server: CTYUN

 

至此,问题原因也非常清楚了,天翼云OOS只支持版本2认证头,不支持版本4认证头。

但是,我在修改我写的DEMO的时候,还是走了很多弯路。

我直接修改配置对象的SignatureVersion = "2",测试发现仍然采用了版本4的认证头。我百思不得其解,抄ctyun-oos-net-core-sdk的代码,甚至引用他的类库,都不行,明明已经胜利在望了,却够不着。

var conf = new AmazonS3Config

    {

        ServiceURL = EndpointUrl,

AuthenticationRegion = "sdqd",

SignatureVersion = "2",

    };

经过仔细对比,终于发现一个疑点,ctyun-oos-net-core-sdk并没有设置AuthenticationRegion,也能够通过认证,我设置了反而通不过,决定删除AuthenticationRegion = "sdqd"这行,居然就通过了!这真是没天理啊!

我理解为,如果设置了AuthenticationRegion,Amazon S3 SDK就自动采用版本4认证,因此,千万不要设置AuthenticationRegion。

 

至此,实现了通过Amazon S3 SDK访问天翼云OSS经典I类型对象存储服务。

 

总结一下代码要点

NuGet安装

<PackageReference Include="AWSSDK.S3" Version="3.7.103.6" />

 

初始化AmazonS3Client客户端对象,

        var credentials = new BasicAWSCredentials(AccessKeyId, AccessKeySecret);

        var conf = new AmazonS3Config

        {

            ServiceURL = $"https://xxx.oos-sdqd.ctyunapi.cn”,

 

            //为了使用版本2认证,千万不能设置认证区域!否则会采用版本4,天翼云不支持版本4认证!

            //AuthenticationRegion = "sdqd",

 

            SignatureVersion = "2",

        };

 

        s3Client = new AmazonS3Client(credentials, conf);

 

PUT上传对象

public async Task<bool> PutObjectAsync(string objectName, Stream stream)

    {

        var req = new PutObjectRequest()

        {

            BucketName = _ossConfig.BucketName,

            Key = objectName,

            InputStream = stream,

        };

 

        var res = await s3Client.PutObjectAsync(req);

 

        if (res.HttpStatusCode == System.Net.HttpStatusCode.OK)

        {

            return true;

        }

        else

        {

            return false;

        }

}

 

标签:Core,cn,天翼云,认证,Amazon,OOS,SDK
From: https://www.cnblogs.com/sunnytrudeau/p/17110705.html

相关文章

  • Asp.Net Core中利用过滤器控制Nginx的缓存时间
    前言Web项目中很多网页资源比如html、js、css通常会做服务器端的缓存,加快网页的加载速度一些周期性变化的API数据也可以做缓存,例如广告资源位数据,菜单数据,商品类目数据,商......
  • 【HMS Core】一张图片带你玩转机器学习服务
    ​1、介绍总览CloudDB(云数据库)是一款端云协同的数据库产品,提供端云数据的协同管理、统一的数据模型和丰富的数据管理API接口等能力。在保证数据的可用性、可靠性、一致......
  • 【HMS Core】推送服务与运动健康服务热门问题汇总
    【推送服务】问题描述:申请自分类权益后,推送数量依旧变少分析原因:自分类权益后,如果没有在每条消息都正确携带importance和category字段会导致频控,所以部分的消息被缓存,没......
  • Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul
     Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul微服务网关Ocelot......
  • Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级
    Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Ocelot+Polly缓存、限流、熔断、降级Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul微服务网关Ocelot加入......
  • .net core概述
    .netcore入门.netcore概述.Netcore中的代码绝大部分是从.netframework中迁移或者改造过来的。ASP.NetCore是一个跨平台的,高性能的开源框架,有以下优点:模块化开发,......
  • .NET Core 6 使用 Nacos
     简介Nacos是DynamicNamingandConfigurationService的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos致力于帮助您发现、......
  • .Net Core 技巧
    设置属性的日期类型ReleaseDate 上的 DataType 特性指定了数据的类型(Date)。通过此特性:用户无需在日期字段中输入时间信息。仅显示日期,而非时间信息。[DataTy......
  • DRF - coreapi自动生成接口文档、JWT
    目录1接口文档1.什么是接口文档2.接口文档的编写方式3.使用coreapi自动生成接口文档步骤(1)安装coreapi(2)配置路由(3)文档说明文字:在视图类,方法上写注释即可(4)配置文件中配置自......
  • ASP.NET Core+Element+SQL Server开发校园图书管理系统(完)
    随着技术的进步,跨平台开发已经成为了标配,在此大背景下,ASP.NETCore也应运而生。本文主要基于ASP.NETCore+Element+SqlServer开发一个校园图书管理系统为例,简述基于MVC三......