Unity | API鉴权用到的函数汇总

目录

一、HMAC-SHA1

二、UriEncode

三、Date

四、Content-MD5

五、参数操作

六、阿里云API鉴权


一、HMAC-SHA1

        使用 RFC 2104 中定义的 HMAC-SHA1 方法生成带有密钥的哈希值:

    private static string CalculateSignature(string secret, string data)
    {
        byte[] keyBytes = Encoding.UTF8.GetBytes(secret);
        byte[] dataBytes = Encoding.UTF8.GetBytes(data);

        using (var hmacsha1 = new HMACSHA1(keyBytes))
        {
            byte[] hashBytes = hmacsha1.ComputeHash(dataBytes);

            // 将哈希值转换为十六进制字符串
            StringBuilder hexString = new StringBuilder(hashBytes.Length * 2);
            foreach (byte b in hashBytes)
            {
                hexString.AppendFormat("{0:x2}", b);
            }
            return hexString.ToString();
        }
    }

二、UriEncode

        按照RFC 3986进行 URI 编码:

private static string Rfc3986Encode(string value)
{
    // 使用 Uri.EscapeDataString 进行初步编码
    var encoded = Uri.EscapeDataString(value);

    // 根据 RFC 3986 的要求替换字符
    encoded = encoded.Replace("%20", "+");
    encoded = encoded.Replace("%21", "!");
    encoded = encoded.Replace("%27", "'");
    encoded = encoded.Replace("%28", "(");
    encoded = encoded.Replace("%29", ")");
    encoded = encoded.Replace("%7E", "~ ");

    return encoded;
}

三、Date

        当前 UTC 时间,以 ISO 8601 yyyyMMddTHHmmssZ 格式表示:

string date = DateTime.UtcNow.ToString("yyyyMMddTHHmmssZ");

        HTTP 1.1 协议中规定的 GMT 时间:(示例:Wed, 01 Mar 2006 12:00:00 GMT )

    public static string GetCurrentDateTimeInStandardFormat()
    {
        // 获取当前时间并转换到指定时区
        var dateTimeOffset = DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(8));

        // 将日期时间格式化为字符串
        var formattedDateTime = dateTimeOffset.ToString("yyyy-MM-ddTHH:mm:sszzz");

        // 替换时区部分的冒号
        return formattedDateTime.Substring(0, 22) + formattedDateTime.Substring(23);
    }

四、Content-MD5

        RFC 1864 定义的请求体(Body) md5 摘要(128 位二进制表示,并使用 base64 编码):

    private static string CalculateMD5(byte[] data)
    {
        using (var md5 = MD5.Create())
        {
            byte[] hashBytes = md5.ComputeHash(data);
            return Convert.ToBase64String(hashBytes);
        }
    }

五、参数操作

        对 URL 中所有参数名、参数值单独 UriEncode,按参数名字母升序的顺序,依次将参数名、参数值用 = 及 & 拼接:

    private static string ConstructCanonicalQueryString(Dictionary<string, string> queryParams)
    {
        if (queryParams == null || queryParams.Count == 0)
            return "";

        var sortedQueryParams = queryParams.OrderBy(kvp => kvp.Key);
        var encodedQueryParams = sortedQueryParams.Select(kvp => $"{Rfc3986Encode(kvp.Key)}={Rfc3986Encode(kvp.Value)}");

        return string.Join("&", encodedQueryParams);
    }

六、阿里云API鉴权

        下方是阿里云上传文件API鉴权及请求示例(其实接入SDK更方便一些)。(阿里云上传文件后路径为https://桶名称.oss-cn-beijing.aliyuncs.com/文件夹/文件

using UnityEngine;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using System;
using System.IO;
using UnityEngine.Networking;


public class AliYunManager : MonoBehaviour
{
    private const string OSS_HOST = "oss-cn-beijing.aliyuncs.com";//域名
    private const string BUCKET_NAME = "*****";//bucket名称
    private const string ACCESS_KEY_ID = "************";
    private const string ACCESS_KEY_SECRET = "**************";

    // Use this for initialization
    void Start()
    {
        UploadFileAsync("D:\\FCJProject\\YiDongYanFaBu\\StudentPartner\\StudentPartner\\Bundles\\StandaloneWindows\\DefaultPackage\\5.0.0\\1ba6bb9f41d66f71f7deb9d2d63b29e4.bundle", "/debug/PC/9.92.0");
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="imagePath">本地文件绝对路径</param>
    /// <param name="bucketPath">需要保存的文件在bucket上的相对路径,前后不需要加'/',也不需要加文件名</param>
    public void UploadFileAsync(string filePath, string bucketPath)
    {
        StartCoroutine(UploadFile(filePath, bucketPath));
    }

    IEnumerator UploadFile(string filePath, string bucketPath)
    {
        // Load the image from file
        byte[] imageBytes = File.ReadAllBytes(filePath);

        string fileName = Path.GetFileName(filePath);
        string bucketFilePath = "/" + bucketPath + "/" + fileName;
        string url = "https://" + BUCKET_NAME + "." + OSS_HOST + bucketFilePath;
        string contentMD5 = "";// ToMD5(imageBytes);
        string contentType = "application/octet-stream";
        string utcGMT = DateTime.UtcNow.ToString("r");
        string canonicalizedOSSHeaders = "";
        string canonicalizedResource = "/" + BUCKET_NAME +bucketFilePath;
        string authorization = GetAuthorization("PUT", contentMD5, contentType, utcGMT, canonicalizedOSSHeaders, canonicalizedResource);
        Debug.Log("Authorization: " + authorization);
        Debug.Log("url: " + url);
        //Debug.Log("contentMD5: " + contentMD5);
        // Create UnityWebRequest
        UnityWebRequest request = new UnityWebRequest(url, "PUT");
        //request.uploadHandler = new UploadHandlerRaw(imageData);
        request.downloadHandler = new DownloadHandlerBuffer();
        // Set headers
        request.SetRequestHeader("Content-Length", imageBytes.Length.ToString());
        request.SetRequestHeader("Content-Type", contentType);
        request.SetRequestHeader("Host", BUCKET_NAME + "." + OSS_HOST);
        request.SetRequestHeader("Date", utcGMT);
        request.SetRequestHeader("Authorization", authorization);

        // Set the body of the request
        UploadHandlerRaw uploadHandler = new UploadHandlerRaw(imageBytes);
        uploadHandler.contentType = contentType;

        request.uploadHandler = uploadHandler;

        // Send the request and wait for a response
        yield return request.SendWebRequest();

        if (request.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError($"Error: {request.error}");
            Debug.LogError($"Response Code: {request.responseCode}");
            Debug.LogError($"Response Text: {request.downloadHandler.text}");

        }
        else
            Debug.Log(request.downloadHandler.text);
    }

    private string GetAuthorization(
        string method, string contentMD5, string contentType,
        string utcGMT, string canonicalizedOSSHeaders, string canonicalizedResource)
    {
        string data = method + "\n"
            + contentMD5 + "\n"
            + contentType + "\n"
            + utcGMT + "\n"
            + canonicalizedOSSHeaders
            + canonicalizedResource;

        Debug.Log("data:"+ data);
        string signature = ToHMACSHA1_Base64(ACCESS_KEY_SECRET, data);
        string authorization = "OSS " + ACCESS_KEY_ID + ":" + signature;

        return authorization;
    }

    private static string ToHMACSHA1_Base64(string key, string data)
    {
        using (HMACSHA1 hmacsha1 = new HMACSHA1(Encoding.UTF8.GetBytes(key)))
        {
            byte[] dataBuffer = Encoding.UTF8.GetBytes(data);
            byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);

            string result = Convert.ToBase64String(hashBytes);
            return result;
        }
    }

    private static string ToMD5(byte[] data)
    {
        using (MD5 md5Hash = MD5.Create())
        {
            byte[] hashBytes = md5Hash.ComputeHash(data);
            Debug.Log(hashBytes.Length);

            return Convert.ToBase64String(hashBytes);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烫青菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值