活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心
      文档中心

      对象存储(经典版)I型

      对象存储(经典版)I型

        • 产品动态
        • 产品简介
        • 产品定义
        • 产品优势
        • 功能特性
        • 应用场景
        • 主要概念
        • 存储桶和文件
        • Account、Service、Bucket和Object
        • 存储类型
        • 合规保留
        • 清单配置
        • 统计分析
        • 操作跟踪
        • 访问控制
        • 数据安全
        • 使用限制
        • 与其他服务的关系
        • 计费说明
        • 计费模式
        • 计费项
        • 按需计费
        • 资源包计费
        • 到期
        • 欠费
        • 快速入门
        • 相关术语解释
        • 服务开通
        • 订购须知
        • 开通OOS服务
        • 资源包订购
        • 资源包续订
        • 资源包退订
        • 控制台快速入门
        • 进入控制台
        • 地域切换
        • 创建存储桶
        • 上传文件
        • 下载文件
        • 控制台指南
        • 进入控制台
        • 域名(Endpoint)
        • 域名(Endpoint)列表
        • 地域切换
        • IAM用户操作权限要求
        • 统计概览
        • 统计概述
        • 概览
        • 统计
        • 容量
        • 删除量
        • 流量
        • 请求次数
        • 并发连接数
        • 数据取回
        • 存储桶管理
        • 存储桶(Bucket)概述
        • 创建存储桶(Bucket)
        • 存储桶列表
        • 删除存储桶(Bucket)
        • 清空存储桶
        • 查看/修改存储桶属性
        • 区域属性
        • 安全策略
        • 网站
        • 日志
        • 生命周期
        • 跨域设置
        • 合规保留
        • 清单配置
        • 文件管理
        • 文件概述
        • 文件列表
        • 查看文件详细信息
        • 上传文件
        • 下载文件
        • 管理文件元数据
        • 预览文件
        • 分享文件
        • 创建文件夹
        • 删除文件或文件夹
        • 复制文件
        • 移动文件
        • 修改存储类型
        • 搜索文件或文件夹
        • 复制文件名称
        • 文件排序
        • 操作跟踪
        • 操作跟踪概述
        • 管理事件记录
        • 跟踪列表
        • 访问控制
        • 访问控制概述
        • 快速入门
        • IAM用户
        • 创建IAM用户
        • 查看和修改IAM用户信息
        • 删除用户
        • IAM子用户登录
        • IAM用户组
        • 创建用户组
        • 查看和修改用户组信息
        • 删除用户组
        • IAM策略
        • 概述
        • IAM策略编写规则
        • Version
        • Statement
        • 系统策略
        • 自定义策略
        • 新建自定义策略
        • 修改自定义策略
        • 删除自定义策略
        • 查看策略基本信息
        • 授权用户/用户组
        • 安全设置
        • 密码安全设置
        • 登录安全设置
        • 安全凭证
        • 密钥
        • 密码
        • MFA
        • 资源包管理
        • API参考
        • 安全策略
        • 用户签名验证(V2)
        • Header中包含签名
        • 使用查询参数验证
        • 用户签名验证(V4)
        • Signature Version 4的工作原理
        • 认证方法
        • 使用Authorization请求头验证
        • 使用查询参数验证
        • Bucket权限控制
        • 访问控制
        • Bucket Policy安全策略
        • 介绍
        • Bucket Policy元素
        • 示例
        • 合规保留
        • 存储桶(Bucket)和文件(Object)
        • OOS API请求结构
        • 关于Service的操作
        • Get Service (List Buckets)
        • Get Regions
        • 关于Bucket的操作
        • PUT Bucket
        • Get Bucket Location
        • GET Bucket ACL
        • GET Bucket (List Objects)
        • DELETE Bucket
        • PUT Bucket Policy
        • GET Bucket Policy
        • DELETE Bucket Policy
        • PUT Bucket Website
        • GET Bucket Website
        • DELETE Bucket Website
        • List Multipart Uploads
        • PUT Bucket Logging
        • GET Bucket Logging
        • HEAD Bucket
        • PUT Bucket Lifecycle
        • GET Bucket Lifecycle
        • DELETE Bucket Lifecycle
        • PUT Bucket CORS
        • GET Bucket CORS
        • DELETE Bucket CORS
        • PUT Bucket Object Lock
        • GET Bucket Object Lock
        • DELETE Bucket Object Lock
        • PUT Bucket Inventory Configuration
        • GET Bucket Inventory Configuration
        • List Bucket Inventory Configuration
        • DELETE Bucket Inventory Configuration
        • 关于Object的操作
        • PUT Object
        • GET Object
        • DELETE Object
        • PUT Object - Copy
        • Initial Multipart Upload
        • Upload Part
        • Complete Multipart Upload
        • Abort Multipart Upload
        • List Parts
        • Copy Part
        • Delete Multiple Objects
        • 断点续传
        • POST Object
        • OPTIONS Object
        • 生成共享链接
        • HEAD Object
        • Backoff说明
        • 错误响应
        • REST错误响应
        • 错误码列表
        • 统计分析
        • 统计API请求结构
        • 统计API概览
        • 统计API
        • GetCapacity
        • GetBilledStorageUsage
        • GetRestoreCapacity
        • GetDeleteCapacity
        • GetTraffics
        • GetRequests
        • GetReturnCode
        • GetConcurrentConnection
        • GetUsage
        • GetBandwidth
        • 错误码列表
        • 操作跟踪
        • 操作跟踪API请求结构
        • 操作跟踪API概览
        • 操作跟踪API
        • CreateTrail
        • DeleteTrail
        • DescribeTrails
        • GetTrailStatus
        • PutEventSelectors
        • GetEventSelectors
        • UpdateTrail
        • StartLogging
        • StopLogging
        • LookupEvents
        • 错误码列表
        • 操作跟踪记录事件列表
        • 访问控制(IAM)
        • IAM API请求结构
        • 访问控制API概览
        • 用户管理接口
        • CreateUser
        • GetUser
        • ListUsers
        • DeleteUser
        • TagUser
        • UntagUser
        • ListUserTags
        • ListGroupForUser
        • CreateAccessKey
        • ListAccessKeys
        • GetAccessKeyLastUsed
        • UpdateAccessKey
        • DeleteAccessKey
        • GetSessionToken
        • CreateLoginProfile
        • GetLoginProfile
        • UpdateLoginProfile
        • DeleteLoginProfile
        • ChangePassword
        • CreateVirtualMFADevice
        • EnableMFADevice
        • ListVirtualMFADevices
        • ListMFADevices
        • DeactivateMFADevice
        • DeleteVirtualMFADevice
        • 用户组管理接口
        • CreateGroup
        • GetGroup
        • AddUserToGroup
        • RemoveUserFromGroup
        • ListGroups
        • DeleteGroup
        • 权限策略管理接口
        • CreatePolicy
        • GetPolicy
        • ListPolicies
        • ListEntitiesForPolicy
        • DeletePolicy
        • AttachUserPolicy
        • ListAttachedUserPolicies
        • DetachUserPolicy
        • AttachGroupPolicy
        • ListAttachedGroupPolicies
        • DetachGroupPolicy
        • UpdateAccountPasswordPolicy
        • GetAccountPasswordPolicy
        • DeleteAccountPasswordPolicy
        • UpdateAccountLoginSecurityPolicy
        • GetAccountLoginSecurityPolicy
        • DeleteAccountLoginSecurityPolicy
        • 服务数量查询
        • 错误码列表
        • IAM策略编写规则
        • 操作权限与API对应关系
        • 常用工具
        • OOS数据迁移工具
        • 介绍
        • 运行环境
        • 迁移步骤
        • 迁移配置文件示例
        • 常见问题
        • 最佳实践
        • 生命周期管理存储桶文件
        • 分享文件
        • 降低恶意访问风险
        • 设置跨域访问
        • 使用S3 Java SDK访问OOS
        • IAM最佳实践
        • 安全管理
        • 用户管理
        • STS临时授权示例
        • 授予其他主账号及主账户下子账号操作名下存储桶的权限
        • 同地域实现内网访问OOS
        • 数据一致性校验
        • 性能优化
        • 使用HttpURLConnection开发
        • 使用V2签名时的HttpURLConnection开发
        • 使用V4签名时的HttpURLConnection开发
        • 数据迁移
        • 本地数据迁移到OOS
        • AWS S3数据迁移到OOS
        • 阿里云OSS数据迁移到OOS
        • OOS之间的数据迁移
        • 图片处理
        • 应用场景
        • 主要概念
        • 参数说明
        • URL构成规则
        • 规则说明
        • 用户签名
        • 接口
        • 图像处理接口
        • 图片水印接口
        • 管道
        • 图片拼接成GIF接口
        • 示例
        • 示例链接
        • 示例代码
        • 常见问题
        • 计费类
        • 计费类常见问题
        • 资源包是否必须购买?是否能指定给具体的存储桶使用?
        • 已购买资源包,为什么仍然扣费?
        • 存储桶内无文件,为什么会产生流量?
        • 哪些资源包会按月更新额度,哪些不会?
        • 如何关闭OOS服务或停止计费?
        • 存储容量和流出流量的关系?
        • 购买类
        • 产品咨询类
        • 产品咨询类常见问题
        • 什么是对象存储网络?
        • 可以上传什么样的文件,大小是否有限制?
        • 什么是存储桶的索引位置和数据位置?
        • 可以在OOS中存储多少数据?
        • OOS是否有图形化管理工具或者命令行工具,帮助用户上传数据到OOS?
        • OOS的持久性和可用性如何?
        • OOS有哪些数据访问方法?
        • 如何保障OOS用户数据的安全?
        • OOS与自建服务器存储对比?
        • 为什么通过OOS控制台访问OOS中的资源时被强制下载?
        • 存储桶(Bucket)和文件(Object)类
        • 存储桶(Bucket)和文件(Object)常见问题
        • 如何创建存储桶(Bucket)?
        • 应该如何使用Bucket?
        • 如何选择使用哪个地域的OOS?
        • 生命周期管理支持哪些场景?
        • 如何获取存储桶的静态网站托管地址?
        • 如何绑定自己的域名?
        • 可以对OOS Bucket进行重命名吗?是否支持Object迁移?
        • OOS支持Bucket作为域名的访问方式吗?
        • 图片上传到OOS,可否生成url,实现图片通过url直接访问预览?
        • 如何获取OOS文件的访问地址?
        • 怎么删除存储桶中的全部文件?
        • 统计分析类
        • 操作跟踪类
        • 访问控制类
        • 访问控制常见问题
        • 新版的IAM与旧版的IAM相比有什么区别?
        • 在绑定MFA页面,输入两组安全码后,提示安全码错误,怎么办?
        • API/SDK类
        • API/SDK常见问题
        • OOS兼容哪些Amazons S3 API?
        • 图片处理类
        • 工具类
        • 视频专区
        • 文档下载
        • OOS开发者文档
        • 用户手册
        • SDK及开发指南
        • 常用工具
        • 相关协议
        • 中国电信天翼云对象存储服务协议
        • 中国电信天翼云对象存储服务等级协议
          无相关产品

          本页目录

          帮助中心对象存储(经典版)I型最佳实践使用HttpURLConnection开发使用V4签名时的HttpURLConnection开发
          使用V4签名时的HttpURLConnection开发
          更新时间 2023-08-01 16:38:49
          • 新浪微博
          • 微信
            扫码分享
          • 复制链接
          最近更新时间: 2023-08-01 16:38:49
          分享文章
          • 新浪微博
          • 微信
            扫码分享
          • 复制链接
          本节主要介绍使用V4签名时的HttpURLConnection开发。

          应用场景

          V4签名下,使用HttpURLConnection开发。

          前提条件

          已开通对象存储(经典版)Ⅰ型服务。

          具体操作

          可以参考下列示例进行HttpURLConnection开发。

          package cn.ctyun.oos.sample;
          
          import java.io.BufferedReader;
          import java.io.InputStream;
          import java.io.InputStreamReader;
          import java.io.OutputStream;
          import java.io.UnsupportedEncodingException;
          import java.net.HttpURLConnection;
          import java.net.URL;
          import java.net.URLEncoder;
          import java.security.MessageDigest;
          import java.text.SimpleDateFormat;
          import java.util.ArrayList;
          import java.util.Collections;
          import java.util.Date;
          import java.util.HashMap;
          import java.util.Iterator;
          import java.util.List;
          import java.util.Map;
          import java.util.SortedMap;
          import java.util.TimeZone;
          import java.util.TreeMap;
          import java.util.regex.Matcher;
          import java.util.regex.Pattern;
          
          import javax.crypto.Mac;
          import javax.crypto.spec.SecretKeySpec;
          
          public class OOSDemoForV4Signer {
          
              private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
              private static final SimpleDateFormat ISO8601_DAY_FORMAT = new SimpleDateFormat("yyyyMMdd");
              private static final char[] HEX_CODE = "0123456789abcdef".toCharArray();
          
              private static final String UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD";
              private static final String SCHEME = "AWS4";
              private static final String ALGORITHM = "HMAC-SHA256";
              private static final String TERMINATOR = "aws4_request";
              private static final String HMAC_SHA256 = "HmacSHA256";
          
              private static final String OOS_ACCESS_KEY = "your_access_key";
              private static final String OOS_SECRET_KEY = "your_secret_key";
              private static final String OOS_ENDPOINT = "oos-cn.ctyunapi.cn";
              private static final String OOS_BUCKET = "your bucket name";
              private static final String OOS_OBJECT_NAME = "your_object_name";
              private static final String OOS_OBJECT_CONTENT = "your_object_content";
          
              private static final int DEFAULT_TIMEOUT = 30000;
          
              static {
                  TimeZone utc = TimeZone.getTimeZone("UTC");
                  ISO8601_DATE_FORMAT.setTimeZone(utc);
                  ISO8601_DAY_FORMAT.setTimeZone(utc);
              }
          
              public static void main(String[] args) throws Exception {
                  OOSDemoForV4Signer demo = new OOSDemoForV4Signer();
                  demo.putObject();
                  demo.getObject();
                  demo.deleteObject();
              }
          
              public void getObject() {
                  try {
                      HttpURLConnection connection = generateConnection("GET", OOS_BUCKET, OOS_OBJECT_NAME);
                      connection.connect();
                      int responseCode = connection.getResponseCode();
                      //  在responseCode为200 的情况下, 可将connection.getInputStream()的对象数据读出。
                      if(responseCode == 200) {
                          System.out.println("get object success");
                      }
                      try (InputStream inputStream =
                          responseCode == 200 ? connection.getInputStream() : connection.getErrorStream()) {
                          BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                          String line;
                          while ((line = reader.readLine()) != null) {
                              System.out.println(line);
                          }
                      }
                  } catch (Exception e) {
                      // 异常可选择抛出或者处理掉。
                      e.printStackTrace();
                  }
              }
          
              public void putObject() {
                  try {
                      HttpURLConnection connection = generateConnection("PUT", OOS_BUCKET, OOS_OBJECT_NAME);
                      connection.setDoOutput(true);
                      connection.connect();
                      // Create the object
                      byte[] requestBody = OOS_OBJECT_CONTENT.getBytes();
                      try (OutputStream outputStream = connection.getOutputStream()) {
                          outputStream.write(requestBody);
                      }
          
                      // Execute the request and print the response
                      int responseCode = connection.getResponseCode();
                      if (responseCode == 200) {
                          System.out.println("put object success");
                      } else {
                          try (InputStream inputStream = connection.getErrorStream()) {
                              BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                              String line;
                              while ((line = reader.readLine()) != null) {
                                  System.out.println(line);
                              }
                          }
                      }
                  } catch (Exception e) {
                      // 异常可选择抛出或者处理掉。
                      e.printStackTrace();
                  }
              }
          
              public void deleteObject() {
                  try {
                      HttpURLConnection connection = generateConnection("DELETE", OOS_BUCKET, OOS_OBJECT_NAME);
                      connection.connect();
                      int responseCode = connection.getResponseCode();
                      if (responseCode == 204) {
                          System.out.println("delete object success");
                      } else {
                          try (InputStream inputStream = connection.getErrorStream()) {
                              BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                              String line;
                              while ((line = reader.readLine()) != null) {
                                  System.out.println(line);
                              }
                          }
                      }
                  } catch (Exception e) {
                      // 异常可选择抛出或者处理掉。
                      e.printStackTrace();
                  }
              }
          
              private HttpURLConnection generateConnection(String method, String bucket, String objectKey) throws Exception {
                  String requestUrl = "http://" + bucket + "." + OOS_ENDPOINT + "/" + urlEncode(objectKey, true);
                  Map<String, String> headers = new HashMap<>();
                  // 1 加在headers里的所有头域,都参与计算签名。
                  // 2 任何头以x-amz-meta-这个前缀开始都会被认为是用户的元数据,当用户检索时,它将会和对象一起被存储并返回。PUT请求头大小限制为8KiB。在PUT请求头中,用户定义的元数据大小限制为2KiB。
                  // headers.put("x-amz-meta-test", "oos");
                  Map<String, String> querys = new HashMap<String, String>();
                  URL url = new URL(requestUrl);
                  String authorization = v4Sign(headers, querys, UNSIGNED_PAYLOAD, url, method);
                  headers.put("Authorization", authorization);
                  HttpURLConnection connection = (HttpURLConnection)new URL(requestUrl).openConnection();
                  connection.setRequestMethod(method);
                  connection.setConnectTimeout(DEFAULT_TIMEOUT);
                  connection.setReadTimeout(DEFAULT_TIMEOUT);
                  headers.forEach(connection::setRequestProperty);
                  return connection;
              }
          
              /** =============== 以下是签名计算相关方法 =============== **/
          
              private String v4Sign(Map<String, String> headers, Map<String, String> queryParameters, String bodyHash,
                  URL endpointUrl, String httpMethod) {
                  String host = endpointUrl.getHost();
                  String serviceName = parseServiceName(host);
                  String regionName = parseRegionName(host);
                  // first get the date and time for the subsequent request, and convert
                  // to ISO 8601 format for use in signature generation
                  Date now = new Date();
                  String dateTimeStamp = ISO8601_DATE_FORMAT.format(now);
          
                  // update the headers with required 'x-amz-date' and 'host' values
                  if (headers == null) {
                      headers = new HashMap<String, String>();
                  }
                  headers.put("x-amz-date", dateTimeStamp);
                  headers.put("x-amz-content-sha256", bodyHash);
          
                  int port = endpointUrl.getPort();
                  if (port > -1 && port != 80 && port != 443) {
                      host = host.concat(":" + Integer.toString(port));
                  }
                  headers.put("Host", host);
          
                  // canonicalize the headers; we need the set of header names as well as the
                  // names and values to go into the signature process
                  String canonicalizedHeaderNames = getCanonicalizeHeaderNames(headers);
                  String canonicalizedHeaders = getCanonicalizedHeaderString(headers);
          
                  // if any query string parameters have been supplied, canonicalize them
                  String canonicalizedQueryParameters = getCanonicalizedQueryString(queryParameters);
          
                  // canonicalize the various components of the request
                  String canonicalRequest = getCanonicalRequest(endpointUrl, httpMethod, canonicalizedQueryParameters,
                      canonicalizedHeaderNames, canonicalizedHeaders, bodyHash);
          
                  // construct the string to be signed
                  String dateStamp = ISO8601_DAY_FORMAT.format(now);
                  String scope = dateStamp + "/" + regionName + "/" + serviceName + "/" + TERMINATOR;
                  String stringToSign = getStringToSign(SCHEME, ALGORITHM, dateTimeStamp, scope, canonicalRequest);
          
                  // compute the signing key
                  byte[] kSigning = createSignatureKey(OOS_SECRET_KEY, dateStamp, regionName, serviceName);
                  byte[] signature = sign(stringToSign, kSigning, HMAC_SHA256);
          
                  String credentialsAuthorizationHeader = "Credential=" + OOS_ACCESS_KEY + "/" + scope;
                  String signedHeadersAuthorizationHeader = "SignedHeaders=" + canonicalizedHeaderNames;
                  String signatureAuthorizationHeader = "Signature=" + toHex(signature);
          
                  String authorizationHeader = SCHEME + "-" + ALGORITHM + " " + credentialsAuthorizationHeader + ", "
                      + signedHeadersAuthorizationHeader + ", " + signatureAuthorizationHeader;
          
                  return authorizationHeader;
              }
          
              private String getCanonicalizedQueryString(Map<String, String> parameters) {
                  if (parameters == null || parameters.isEmpty()) {
                      return "";
                  }
          
                  SortedMap<String, String> sorted = new TreeMap<String, String>();
                  Iterator<Map.Entry<String, String>> pairs = parameters.entrySet().iterator();
                  while (pairs.hasNext()) {
                      Map.Entry<String, String> pair = pairs.next();
                      String key = pair.getKey();
                      String value = pair.getValue();
                      sorted.put(urlEncode(key, false), urlEncode(value, false));
                  }
          
                  StringBuilder builder = new StringBuilder();
                  pairs = sorted.entrySet().iterator();
                  while (pairs.hasNext()) {
                      Map.Entry<String, String> pair = pairs.next();
                      builder.append(pair.getKey());
                      builder.append("=");
                      builder.append(pair.getValue());
                      if (pairs.hasNext()) {
                          builder.append("&");
                      }
                  }
          
                  return builder.toString();
              }
          
              private String getCanonicalizedHeaderString(Map<String, String> headers) {
                  if (headers == null || headers.isEmpty()) {
                      return "";
                  }
          
                  // step1: sort the headers by case-insensitive order
                  List<String> sortedHeaders = new ArrayList<String>();
                  sortedHeaders.addAll(headers.keySet());
                  Collections.sort(sortedHeaders, String.CASE_INSENSITIVE_ORDER);
          
                  // step2: form the canonical header:value entries in sorted order.
                  // Multiple white spaces in the values should be compressed to a single
                  // space.
                  StringBuilder buffer = new StringBuilder();
                  for (String key : sortedHeaders) {
                      buffer.append(key.toLowerCase().replaceAll("\\s+", " ") + ":" + headers.get(key).replaceAll("\\s+", " "));
                      buffer.append("\n");
                  }
          
                  return buffer.toString();
              }
          
              private String getCanonicalizeHeaderNames(Map<String, String> headers) {
                  List<String> sortedHeaders = new ArrayList<String>();
                  sortedHeaders.addAll(headers.keySet());
                  Collections.sort(sortedHeaders, String.CASE_INSENSITIVE_ORDER);
          
                  StringBuilder buffer = new StringBuilder();
                  for (String header : sortedHeaders) {
                      if (buffer.length() > 0)
                          buffer.append(";");
                      buffer.append(header.toLowerCase());
                  }
          
                  return buffer.toString();
              }
          
              private String getCanonicalRequest(URL endpoint, String httpMethod, String queryParameters,
                  String canonicalizedHeaderNames, String canonicalizedHeaders, String bodyHash) {
                  String canonicalRequest;
                  if (bodyHash == null || bodyHash.equals("")) {
                      canonicalRequest = httpMethod + "\n" + getCanonicalizedResourcePath(endpoint) + "\n" + queryParameters
                          + "\n" + canonicalizedHeaders + "\n" + canonicalizedHeaderNames;
                  } else {
                      canonicalRequest = httpMethod + "\n" + getCanonicalizedResourcePath(endpoint) + "\n" + queryParameters
                          + "\n" + canonicalizedHeaders + "\n" + canonicalizedHeaderNames + "\n" + bodyHash;
                  }
                  return canonicalRequest;
              }
          
              private String getStringToSign(String scheme, String algorithm, String dateTime, String scope,
                  String canonicalRequest) {
                  String stringToSign =
                      scheme + "-" + algorithm + "\n" + dateTime + "\n" + scope + "\n" + toHex(hash(canonicalRequest));
                  return stringToSign;
              }
          
              private byte[] createSignatureKey(String key, String dateStamp, String regionName, String serviceName) {
                  byte[] kSecret = (SCHEME + key).getBytes();
                  byte[] kDate = sign(dateStamp, kSecret, HMAC_SHA256);
                  byte[] kRegion = sign(regionName, kDate, HMAC_SHA256);
                  byte[] kService = sign(serviceName, kRegion, HMAC_SHA256);
                  byte[] kSigning = sign(TERMINATOR, kService, HMAC_SHA256);
                  return kSigning;
              }
          
              private byte[] sign(String stringData, byte[] key, String algorithm) {
                  try {
                      byte[] data = stringData.getBytes("UTF-8");
                      Mac mac = Mac.getInstance(algorithm);
                      mac.init(new SecretKeySpec(key, algorithm));
                      return mac.doFinal(data);
                  } catch (Exception e) {
                      throw new RuntimeException("Unable to calculate a request signature: " + e.getMessage(), e);
                  }
              }
          
              private String getCanonicalizedResourcePath(URL endpoint) {
                  if (endpoint == null) {
                      return "/";
                  }
                  String path = endpoint.getPath();
                  if (path == null || path.isEmpty()) {
                      return "/";
                  }
          
                  // String encodedPath = urlEncode(path, true);
                  String encodedPath = path;
                  if (encodedPath.startsWith("/")) {
                      return encodedPath;
                  } else {
                      return "/".concat(encodedPath);
                  }
              }
          
              private String urlEncode(String url, boolean keepPathSlash) {
                  String encoded;
                  try {
                      encoded = URLEncoder.encode(url, "UTF-8");
                  } catch (UnsupportedEncodingException e) {
                      throw new RuntimeException("UTF-8 encoding is not supported.", e);
                  }
                  if (keepPathSlash) {
                      encoded = encoded.replace("%2F", "/");
                  }
                  return encoded;
              }
          
              private String toHex(byte[] data) {
                  StringBuilder r = new StringBuilder(data.length * 2);
                  for (byte b : data) {
                      r.append(HEX_CODE[(b >> 4) & 0xF]);
                      r.append(HEX_CODE[(b & 0xF)]);
                  }
                  return r.toString();
              }
          
              private byte[] hash(String text) {
                  try {
                      MessageDigest md = MessageDigest.getInstance("SHA-256");
                      md.reset();
                      md.update(text.getBytes("UTF-8"));
                      return md.digest();
                  } catch (Exception e) {
                      throw new RuntimeException("Unable to compute hash while signing request: " + e.getMessage(), e);
                  }
              }
          
              private String parseRegionName(String host) {
                  String pattern = "oos-([\\w-]*).ctyunapi.cn$";
                  Pattern r = Pattern.compile(pattern);
                  Matcher m = r.matcher(host);
                  if (m.find()) {
                      return m.group(1).toLowerCase();
                  } else {
                      throw new RuntimeException("parse region error, please check endpoint.");
                  }
              }
          
              private String parseServiceName(String host) {
                  if (host.endsWith("-iam.ctyunapi.cn")) {
                      return "sts";
                  } else {
                      return "s3";
                  }
              }
          }
          
          文档反馈

          建议您登录后反馈,可在建议与反馈里查看问题处理进度

          鼠标选中文档,精准反馈问题

          选中存在疑惑的内容,即可快速反馈问题,我们会跟进处理

          知道了

          上一篇 :  使用V2签名时的HttpURLConnection开发
          下一篇 :  数据迁移
          搜索 关闭
          ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
          公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
          备案 京公网安备11010802043424号 京ICP备 2021034386号
          ©2025天翼云科技有限公司版权所有
          京ICP备 2021034386号
          备案 京公网安备11010802043424号
          增值电信业务经营许可证A2.B1.B2-20090001
          用户协议 隐私政策 法律声明