View a markdown version of this page

使用校验和实现数据完整性保护 - 适用于 Kotlin 的 AWS SDK

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

使用校验和实现数据完整性保护

Amazon Simple Storage Service (Amazon S3) 允许您在上传对象时指定校验和。当您指定校验和时,校验和与对象一起存储,并且可以在下载对象时验证该校验和。

传输文件时,校验和可提供额外的数据层完整性。使用校验和,您可以通过确认收到文件与原始文件是否匹配来验证数据一致性。有关 Amazon S3 校验和的更多信息,请参阅 Amazon Simple Storage Service 用户指南,包括支持的算法

您可以灵活地选择最适合自己需求的算法,并让 SDK 计算校验和。或者,您也可以使用任一受支持的算法,提供预先计算好的校验和值。

注意

从的 1.4.0 版开始 适用于 Kotlin 的 AWS SDK,SDK 通过自动计算上传的CRC32校验和来提供默认的完整性保护。如果您未提供预先计算的校验和值,或者未指定 SDK 计算校验和时应使用的算法,则 SDK 会计算此校验和。

SDK 还提供数据完整性保护的全局设置,您可以在外部进行设置,您可以在AWS SDKs 和工具参考指南中阅读这些设置。

我们在两个请求阶段讨论校验和:上传对象和下载对象。

上传对象

您可以使用带请求参数的 putObject 函数,通过适用于 Kotlin 的 SDK 将对象上传到 Amazon S3。请求数据类型提供用于启用校验和计算的 checksumAlgorithm 属性。

以下代码段展示了上传具有 CRC32 校验和的对象的请求。当 SDK 发送请求时,它会计算 CRC32 校验和并上传对象。Amazon S3 将校验和与对象一起存储。

val request = PutObjectRequest { bucket = "amzn-s3-demo-bucket" key = "key" checksumAlgorithm = ChecksumAlgorithm.CRC32 }

如果您未在请求中提供校验和算法,则校验和行为将根据您使用的 SDK 版本而异,具体如下表所示。

未提供校验和算法时的校验和行为

Kotlin SDK 版本 校验和行为
1.4.0 之前的版本 SDK 不会自动计算基于 CRC 的校验和,也不会在请求中提供该值。
1.4.0 或更高版本

SDK 使用 CRC32 算法计算校验和,并在请求中提供该值。Amazon S3 通过计算自己的 CRC32 校验和并将其与 SDK 提供的校验和进行对比,从而验证传输的完整性。如果校验和匹配,则校验和将与对象一起保存。

使用预先计算的校验和值

与请求一起提供的预先计算校验和值会禁用 SDK 的自动计算,而是使用提供的值。

以下示例显示了具有预先计算的 SHA256校验和的请求。

val request = PutObjectRequest { bucket = "amzn-s3-demo-bucket" key = "key" body = ByteStream.fromFile(File("file_to_upload.txt")) checksumAlgorithm = ChecksumAlgorithm.SHA256 checksumSha256 = "cfb6d06da6e6f51c22ae3e549e33959dbb754db75a93665b8b579605464ce299" }

如果 Amazon S3 确定指定算法的校验和值不正确,服务就会返回错误响应。

分段上传

您也可以将校验和用于分段上传。

您必须在 CreateMultipartUpload 请求和每个 UploadPart 请求中指定校验和算法。最后一步,您必须在 CompleteMultipartUpload 中指定每个分段的校验和。以下示例展示了如何创建具有指定校验和算法的分段上传。

val multipartUpload = s3.createMultipartUpload { bucket = "amzn-s3-demo-bucket" key = "key" checksumAlgorithm = ChecksumAlgorithm.Sha1 } val partFilesToUpload = listOf("data-part1.csv", "data-part2.csv", "data-part3.csv") val completedParts = partFilesToUpload .mapIndexed { i, fileName -> val uploadPartResponse = s3.uploadPart { bucket = "amzn-s3-demo-bucket" key = "key" body = ByteStream.fromFile(File(fileName)) uploadId = multipartUpload.uploadId partNumber = i + 1 // Part numbers begin at 1. checksumAlgorithm = ChecksumAlgorithm.Sha1 } CompletedPart { eTag = uploadPartResponse.eTag partNumber = i + 1 checksumSha1 = uploadPartResponse.checksumSha1 } } s3.completeMultipartUpload { uploadId = multipartUpload.uploadId bucket = "amzn-s3-demo-bucket" key = "key" multipartUpload { parts = completedParts } }

下载对象

使用 getObject 方法下载对象时,在以下情况下 SDK 会自动验证校验和:如果适用于 GetObjectRequest 的生成器的 checksumMode 属性设置为 ChecksumMode.Enabled

以下代码段中的请求引导 SDK 通过计算校验和并比较值来验证响应中的校验和。

val request = GetObjectRequest { bucket = "amzn-s3-demo-bucket" key = "key" checksumMode = ChecksumMode.Enabled }
注意

如果上传对象时没有使用校验和,则不会进行验证。

如果您使用的是 1.4.0 或更高版本的 SDK,SDK 会自动检查 getObject 请求的完整性,而无需将 checksumMode = ChecksumMode.Enabled 添加到请求中。

异步验证

由于适用于 Kotlin 的 SDK 在从 Amazon S3 下载对象时使用流式响应,因此将在您使用该对象时计算校验和。因此,您必须使用该对象才能验证校验和。

以下示例展示了如何通过充分使用响应来验证校验和。

val request = GetObjectRequest { bucket = "amzn-s3-demo-bucket" key = "key" checksumMode = checksumMode.Enabled } val response = s3Client.getObject(request) { println(response.body?.decodeToString()) // Fully consume the object. // The checksum is valid. }

相比之下,以下示例中的代码并未以任何方式使用该对象,因此不会验证校验和。

s3Client.getObject(request) { println("Got the object.") }

如果由 SDK 计算的校验和与随响应一起发送的预期校验和不匹配,SDK 就会抛出 ChecksumMismatchException