华为云Api调用怎么生成Authorization鉴权信息,StringToSign拼接流程

news2024/9/20 6:22:25

请求示例 

Authorization

为了安全,华为云的 Api 调用都是需要在请求的 Header 中携带 Authorization 鉴权的,这个鉴权15分钟内有效,超过15分钟就不能用了,而且是需要调用方自己手动拼接的。

Authorization的格式为

OBS 用户AK:手动生成的Signature

Signature生成

Signature生成流程:

 参考文档:Header中携带签名_对象存储服务 OBS

Signature生成代码

package com.fdw.algorithm.HWCloud;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class SignDemo {
	
    private static final String SIGN_SEP = "\n";
    private static final String OBS_PREFIX = "x-obs-";
    private static final String DEFAULT_ENCODING = "UTF-8";
    private static final List<String> SUB_RESOURCES = Collections.unmodifiableList(Arrays.asList(
        "CDNNotifyConfiguration", "acl", "append", "attname", "backtosource", "cors", "customdomain", "delete",
   	"deletebucket", "directcoldaccess", "encryption", "inventory", "length", "lifecycle", "location", "logging",
   	"metadata", "mirrorBackToSource", "modify", "name", "notification", "obscompresspolicy",  "orchestration", 
   	"partNumber", "policy", "position", "quota","rename", "replication", "response-cache-control", 
   	"response-content-disposition","response-content-encoding", "response-content-language", "response-content-type", 
   	"response-expires","restore", "storageClass", "storagePolicy", "storageinfo", "tagging", "torrent", "truncate",
   	"uploadId", "uploads", "versionId", "versioning", "versions", "website", "x-image-process",
  	 "x-image-save-bucket", "x-image-save-object", "x-obs-security-token", "object-lock", "retention"));
 
    private String ak;
    private String sk;
    // 对字符串进行UTF8编码
    public String urlEncode(String input) throws UnsupportedEncodingException {
        return URLEncoder.encode(input, DEFAULT_ENCODING)
            .replaceAll("%7E", "~") //for browser
            .replaceAll("%2F", "/")
            .replaceAll("%20", "+");
    }
 
    private String join(List<?> items, String delimiter) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < items.size(); i++) {
            String item = items.get(i).toString();
            sb.append(item);
            if (i < items.size() - 1) {
                sb.append(delimiter);
            }
        }
        return sb.toString();
    }
	
    private boolean isValid(String input) {
        return input != null && !input.equals("");
    }

    // 使用访问密钥SK计算HmacSHA1值
    public String hmacSha1(String input) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
        SecretKeySpec signingKey = new SecretKeySpec(this.sk.getBytes(DEFAULT_ENCODING), "HmacSHA1");
        // 获取Mac实例,并通过getInstance方法指定使用HMAC-SHA1算法
        Mac mac = Mac.getInstance("HmacSHA1");
        // 使用访问密钥SK初始化Mac对象
        mac.init(signingKey);
        return Base64.getEncoder().encodeToString(mac.doFinal(input.getBytes(DEFAULT_ENCODING)));
    }

    // 构造StringToSign
    private String stringToSign(String httpMethod, Map<String, String[]> headers, Map<String, String> queries,
        String bucketName, String objectName) throws Exception{
        String contentMd5 = "";
        String contentType = "";
        String date = "";
		
        TreeMap<String, String> canonicalizedHeaders = new TreeMap<String, String>();
		
        String key;
        List<String> temp = new ArrayList<String>();
        for(Map.Entry<String, String[]> entry : headers.entrySet()) {
            key = entry.getKey();
            if(key == null || entry.getValue() == null || entry.getValue().length == 0) {
                continue;
            }
			
            key = key.trim().toLowerCase(Locale.ENGLISH);
            if(key.equals("content-md5")) {
                contentMd5 = entry.getValue()[0];
                continue;
            }
			
            if(key.equals("content-type")) {
                contentType = entry.getValue()[0];
                continue;
            }
			
            if(key.equals("date")) {
                date = entry.getValue()[0];
                continue;
            }
			
            if(key.startsWith(OBS_PREFIX)) {				
                for(String value : entry.getValue()) {
                    if(value != null) {
                        temp.add(value.trim());
                    }
                }
                canonicalizedHeaders.put(key, this.join(temp, ","));
                temp.clear();
            }
        }
	    // 如果header头域中包含x-obs-date,Date参数置空
        if(canonicalizedHeaders.containsKey("x-obs-date")) {
            date = "";
        }	
		
        // 构造StringToSign,拼接HTTP-Verb、Content-MD5、Content-Type、Date
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append(httpMethod).append(SIGN_SEP)
            .append(contentMd5).append(SIGN_SEP)
            .append(contentType).append(SIGN_SEP)
            .append(date).append(SIGN_SEP);
			
        // 构造StringToSign,拼接CanonicalizedHeaders
        for(Map.Entry<String, String> entry : canonicalizedHeaders.entrySet()) {
            stringToSign.append(entry.getKey()).append(":").append(entry.getValue()).append(SIGN_SEP);
        }
		
        // 构造StringToSign,拼接CanonicalizedResource
        stringToSign.append("/");
        if(this.isValid(bucketName)) {
            stringToSign.append(bucketName).append("/");
            if(this.isValid(objectName)) {
                stringToSign.append(this.urlEncode(objectName));
            }
        }
		
        TreeMap<String, String> canonicalizedResource = new TreeMap<String, String>();
        for(Map.Entry<String, String> entry : queries.entrySet()) {
            key = entry.getKey();
            if(key == null) {
                continue;
            }

            if(SUB_RESOURCES.contains(key)) {
                canonicalizedResource.put(key, entry.getValue());
            }
        }
		
        if(canonicalizedResource.size() > 0) {
            stringToSign.append("?");
            for(Map.Entry<String, String> entry : canonicalizedResource.entrySet()) {
                stringToSign.append(entry.getKey());
                if(this.isValid(entry.getValue())) {
                    stringToSign.append("=").append(entry.getValue());
                }
                stringToSign.append("&");
            }
            stringToSign.deleteCharAt(stringToSign.length()-1);
        }
		
        // System.out.println(String.format("StringToSign:%s%s", SIGN_SEP, stringToSign.toString()));
		
        return stringToSign.toString();
    }
	
    public String headerSignature(String httpMethod, Map<String, String[]> headers, Map<String, String> queries, String bucketName, String objectName) throws Exception {

        // 构造stringToSign
        String stringToSign = this.stringToSign(httpMethod, headers, queries, bucketName, objectName);
        System.out.println("stringToSign: "+stringToSign);
		
        // 计算签名
        return String.format("OBS %s:%s", this.ak, this.hmacSha1(stringToSign));
    }
	
    public static void main(String[] args) throws Exception {
        SignDemo demo = new SignDemo();

        /* 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;
        本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。*/
        //demo.ak = System.getenv("HUAWEICLOUD_SDK_AK");
        //demo.sk = System.getenv("HUAWEICLOUD_SDK_SK");

        //最好用上面的方法赋值,这里只是简化操作
        demo.ak = "ZI6KNMNGWZUWMJV5WMKW";
        demo.sk = "hIAb8jwgPEHTYknEMKql6DRqGZMLxRY66cHzd8D2";
		
        String bucketName = "bucket-test";
        String objectName = "hello.jpg";
        Map<String, String[]> headers = new HashMap<String, String[]>();
        headers.put("date", new String[] {"Wed, 14 Aug 2024 07:20:28 GMT"});
        //headers.put("x-obs-acl", new String[] {"public-read"});
        //headers.put("x-obs-meta-key1", new String[] {"value1"});
        //headers.put("x-obs-meta-key2", new String[] {"value2", "value3"});
        Map<String, String> queries = new HashMap<String, String>();
        //queries.put("acl", null);


        //计算Header中携带的签名	
        System.out.println(demo.headerSignature("GET", headers, queries, null, null));
    }
	
}

注意

代码中的 date 是手动填写的时间,必须为RFC 1123格式的GMT时间(和北京时间差了8个小时),与系统当前时间差不能超过15分钟。

 与请求头中的时间也要保持一致,分秒不差!!!

演示成果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2039922.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

zabbix agent 可用性 为 灰色

解决zabbix可用性为灰色状态 配置–》模板–》选择模板&#xff0c; 之后正常。

排序: 插入\希尔\选择\归并\冒泡\快速\堆排序实现

1.排序的概念及应用 1.1概念 排序:所谓排序&#xff0c;就是一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 1.2运用 购物筛选排序&#xff1a; 1.3常见排序算法 2.实现常见的排序算法 int a[ {5,3,9,6,2,4,7,1,8}; 2…

MySQL数据库专栏(三)数据库服务维护操作

1、界面维护&#xff0c;打开服务窗口找到MySQL服务&#xff0c;右键单击可对服务进行启动、停止、重启等操作。 选择属性&#xff0c;还可以设置启动类型为自动、手动、禁用。 2、指令维护 卸载服务&#xff1a;sc delete [服务名称] 例如&#xff1a;sc delete MySQL 启动服…

嵌入式软件开发学习一:软件安装(保姆级教程)

资源下载&#xff1a; 江协科技提供&#xff1a; 资料下载 一、安装Keil5 MDK 1、双击.EXE文件&#xff0c;开始安装 2、 3、 4、此处尽量不要安装在C盘&#xff0c;安装路径选择纯英文&#xff0c;防止后续开发报错 5、 6、 7、弹出来的窗口全部关闭&#xff0c;进入下一步&a…

STM32(一):新建工程

stm32f10x.h文件&#xff1a;描述stm32有哪些寄存器&#xff08;外围&#xff09;和它对应的地址。stm32由内核和内核外围的设备组成的&#xff0c;内核寄存器描述和外围寄存器描述文件存储位置不在一起core_cm3.h core_cm3.c内核寄存器描述文件。mic.c内核库函数 stm32f10x_co…

【初阶数据结构】通讯录项目(可用作课程设计)

文章目录 概述1. 通讯录的效果2. SeqList.h3. Contact.h4. SeqList.c5. Contact.c6. test.c 概述 通讯录项目是基于顺序表这个数据结构来实现的。如果说数组是苍蝇小馆&#xff0c;顺序表是米其林的话&#xff0c;那么通讯录就是国宴。 换句话说&#xff0c;通讯录就是顺序表…

pycharm windows/mac 指定多版本python

一、背景 工作中经常会使用不同版本的包&#xff0c;如同时需要tf2和tf1&#xff0c;比较新的tf2需要更高的python版本才能安装&#xff0c;而像tf1.5 需要低版本的python 才能安装&#xff08;如 python3.6&#xff09;,所以需要同时安装多个版本。 二、安装多版本python py…

会员系统开发,检测按钮位置,按钮坐标,弹出指定位置对话框-SAAS 本地化及未来之窗行业应用跨平台架构

一 获取元素坐标 var 按钮_obj document.querySelector(#未来之窗玄武id);var 按钮_rect 按钮_obj.getBoundingClientRect()console.log(按钮_rect);输出结果 bottom : 35 height : 21 left : 219.921875 right : 339.921875 top : 14 width : 120 x : 219.921875 y…

R语言统计分析——组间差异的非参数检验

参考资料&#xff1a;R语言实战【第2版】 如果数据无法满足t检验或ANOVA的参数假设&#xff0c;可以转而使用非参数检验。举例来说&#xff0c;若结果变量在本质上就严重偏倚或呈现有序关系&#xff0c;那么可以考虑非参数检验。 1、两组的比较 若两组数据独立&#xff0c;可以…

大厂进阶五:React源码解析之Diff算法

本文主要针对React源码进行解析&#xff0c;内容有&#xff1a; 1、Diff算法原理、两次遍历 一、Diff源码解析 以下是关于 React Diff 算法的详细解析及实例&#xff1a; 1、React Diff 算法的基本概念和重要性 1.1 概念 React Diff 算法是 React 用于比较虚拟 DOM 树之间…

初识C++ · 类型转换

目录 前言&#xff1a; 1 C中的类型转换 1.1 static_cast 1.2 reinterpret_cast 1.3 const_cast 1.4 dynamic_cast 前言&#xff1a; C可以说是恨死了隐式类型转换&#xff0c;你可能会疑问了&#xff0c;为什么&#xff1f;不是单参数隐式类型转换为自定义类型的时候人…

苹果笔记本电脑可以玩steam游戏吗 MacBook支持玩steam游戏吗 在Steam上玩黑神话悟空3A大作 苹果Mac怎么下载steam

游戏是生活的润滑剂&#xff0c;越来越多的用户开始关注Mac平台上可玩的游戏。幸运的是&#xff0c;Steam作为最大的数字发行平台之一&#xff0c;提供了大量适用于Mac操作系统的游戏。无论你是喜欢策略、冒险还是射击类游戏&#xff0c;都能在Steam上找到适合自己Mac设备玩耍的…

ESP32CAM人工智能教学18

ESP32CAM人工智能教学18 获取数据并显示 如果我们给ESP32Cam外挂一些传感器&#xff08;比如温湿度传感器、超声波测距传感器、红外人体传感器等&#xff09;&#xff0c;我们怎么把ESP32Cam捕获到的数据&#xff0c;传递到客户端的浏览器&#xff0c;并在网页index.html中显示…

WordPress网站速度优化

提升网站速度对用户体验和搜索引擎排名至关重要。无论你是新手博主&#xff0c;还是经验丰富的网站开发人员&#xff0c;要想优化WordPress网站&#xff0c;需要长时间的努力和坚持。以下是按入门、中级和专家级别介绍的12个实用方法&#xff0c;帮助你提升WordPress网站的整体…

zabbix监控进程,日志,主从状态和主从延迟

自定义监控进程 使用httpd服务为例&#xff0c;监控httpd的进程 在zabbix-agent上安装httpd yum -y install httpd 重启httpd systemctl restart httpd systemtctl enable httpd 查看httpd的进程 [rootzabbix-agent ~]# ps -ef | grep httpd root 2407458 1 0 16:…

soapui调用接口参数传递嵌套xml,多层CDATA表达形式验证

1.环境信息 开发工具&#xff1a;idea 接口测试工具&#xff1a;soapui 编程语言&#xff1a;java 项目环境&#xff1a;jdk1.8 webservice&#xff1a;jdk自带的jws 处理xml&#xff1a;jdk自带的jaxb 2.涉及代码 package org.example.webdemo;import javax.jws.WebMethod; i…

Python,Spire.Doc模块,处理word、docx文件,极致丝滑

Python处理word文件&#xff0c;一般都是推荐的Python-docx&#xff0c;但是只写出一个&#xff0c;一句话的文件&#xff0c;也没有什么样式&#xff0c;就是36K。 再打开word在另存一下&#xff0c;就可以到7-8k&#xff0c;我想一定是python-docx的问题&#xff0c;但一直没…

汽车免拆诊断案例 | DAF(达富)汽油尾气处理液故障警示

故障现象 距离我上次在货卡上工作已经有一段时间了&#xff0c;让它们在道路上保持安全行驶是非常重要的。因此&#xff0c;当故障警示灯亮起时&#xff0c;我们需要迅速找到问题方向以及排除故障。 车辆的仪表板亮起多个故障灯以及警示灯&#xff0c;我们需要用解码器查找触…

数据分析与应用:微信-情人节红包流向探索分析

目录 0 需求描述 1 红包发送方用户的基本信息缺失率有多高?(即有多少红包发送方用户无法在用户基本信息表中匹配? 2 哪一组红包金额的拒收率最高? 3、最受二线城市欢迎的红包金额为?(即发出次数最多) 4 北上广深 4 大城市中,哪座城市的男性用户发出的 520 红包比例…

《密码编码学与网络安全原理与实践》第十四章第十五章密钥管理和用户认证

密钥管理与分发 密钥分发管理 传统上&#xff0c;对称加密被用于实现消息的保密性&#xff08;confidentiality&#xff09; 面临的攻击&#xff1a;局域网内监听、搭线窃听 传输媒介&#xff1a;线缆(双绞线、同轴电缆、光纤) (电磁波干扰)、微波链路、卫星信道 保密通信…