zoukankan      html  css  js  c++  java
  • 阿里云OSS-web端直传的服务端签名算法

    web直传的好处:用户通过浏览器直接上传到阿里云OSS,对web服务器没有压力!

    这里的服务端代码仅仅用来计算签名,不处理上传!如果.net服务端直传(支持分片和断点续传),参考OSS .NET SDK(https://help.aliyun.com/document_detail/32090.html)

    WEB端表单上传,需要签名域Signature,通过js计算签名,AccessKeyID和AcessKeySecret会暴露在前端页面,严重安全隐患,因此用服务端计算签名再返回给浏览器,浏览器通过表单(multipart/form-data 编码)的方式就可以直接上传文件到OSS了,

    阿里官网文档https://help.aliyun.com/document_detail/31926.html (Java,Python,PHP,Go,Ruby签名示例)没有提供C#版本的签名计算代码,这里提供一个供参考

    PostObject API参考: https://help.aliyun.com/document_detail/31988.html

    什么是Post Policy?

    Post请求的policy表单域用于验证请求的合法性。 policy为一段经过UTF-8和base64编码的JSON文本,声明了Post请求必须满足的条件。

    Policy表单域的示例 (JSON格式)

    { "expiration": "2014-12-01T12:00:00.000Z","conditions": [{"bucket": "johnsmith" },["starts-with", "$key", "user/eric/"]]}

    注意:Post policy中必须包含expiration和condtions。

    什么是Post Signature

    Post请求的Signature表单域是根据Policy计算的

    计算Signature的具体流程为

    1. 创建一个 UTF-8 编码的 policy。
    2. 将 policy 进行 base64 编码,其值即为 policy 表单域该填入的值,将该值作为将要签名的字符串。
    3. 使用 AccessKeySecret 对要签名的字符串进行签名。

     C#签名代码(MVC)

    前提:需要安装aliyun.oss.sdk和Newtonsoft.Json的nuget包

     public class AliyunController : MyControllerBase
        {
            public string accessKeyId = System.Configuration.ConfigurationManager.AppSettings["aliyun_ak_id"];//请填写您的AccessKeyId。
            public string accessKeySecret = System.Configuration.ConfigurationManager.AppSettings["aliyun_ak_secret"];//请填写您的AccessKeySecret
            public string bucket = System.Configuration.ConfigurationManager.AppSettings["aliyun_bucket"];//请填写您的bucket name
            // GET: Aliyun
            public ContentResult GetPostObjectSignature(int courseId)
            {
                string host = "http://"+ bucket + ".oss-cn-shanghai.aliyuncs.com";//请填写您的bucket endpoint。
    
                const string endpoint = "http://oss-cn-shanghai.aliyuncs.com";//请填写您的endpoint
    
                //第一步,构造policy
                var dir = "zhangsan/";//设置当前用户上传指定的前缀,必须以斜线结尾,类似目录(OSS不存在多级目录,但是可以模拟)
                var expiration = DateTime.Now.AddMinutes(100);
                var policyConds = new PolicyConditions();
                policyConds.AddConditionItem(MatchMode.StartWith, PolicyConditions.CondKey, dir);//上传目录
                policyConds.AddConditionItem(PolicyConditions.CondContentLengthRange, 1, 1048576000);//允许上传的文件大小限制       
            var ossClient = new OssClient(endpoint, accessKeyId, accessKeySecret);//调用阿里云SDK的API
            var postPolicy = ossClient.GeneratePostPolicy(expiration, policyConds);//给policyConds添加过期时间并json序列化(格式iso8601:"yyyy-MM-dd'T'HH:mm:ss.fff'Z'")
    
                /*生成的Policy范例
                    {"expiration":"2017-05-17T20:23:23Z","conditions":[["content-length-range",0,1048576000],["starts-with","$key","zhangsan"]]}
                    */
                //第二步 将policy 的json字符串进行base64编码
    
                var base64Policy = Convert.ToBase64String(Encoding.UTF8.GetBytes(postPolicy));
    
                //第三步,生成签名(哈希算法)
                var signature = ComputeSignature(accessKeySecret, base64Policy);//生成签名
                
                 //以下返回给前端表单域或者阿里云OSS的js api
                TimeSpan ts = expiration - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                var expire = Convert.ToInt64(ts.TotalSeconds);
    
                Dictionary<string, object> response_dic = new Dictionary<string, object>();
                response_dic["accessid"] = accessKeyId;
                response_dic["host"] = host;
                response_dic["policy"] = base64Policy;
                response_dic["signature"] = signature;
                response_dic["expire"] = expire;
                //这个参数是设置用户上传指定的前缀
                response_dic["dir"] = dir;
                return Content(JsonConvert.SerializeObject(response_dic));
            }
          private string ComputeSignature(string key, string data)
            {
                using (var algorithm = KeyedHashAlgorithm.Create("HmacSHA1".ToUpperInvariant()))
                {
                    algorithm.Key = Encoding.UTF8.GetBytes(key.ToCharArray());
                    return Convert.ToBase64String(
                        algorithm.ComputeHash(Encoding.UTF8.GetBytes(data.ToCharArray())));
                }
            }
    
    }
  • 相关阅读:
    树链剖分
    后缀自动机
    莫队算法。
    线性递推BM模板
    笛卡尔积
    2019牛客暑期多校训练营(第三场) J LRU management 模拟链表操作
    线性基
    bitset 位运算
    Lindström–Gessel–Viennot lemma定理 行列式板子
    三角形
  • 原文地址:https://www.cnblogs.com/imust2008/p/6869146.html
Copyright © 2011-2022 走看看