aliyun oss js直传且使用服务器端生成签名

时间:2017-05-17 20:00:18   收藏:0   阅读:4093

采用JS客户端直接签名有一个很严重的安全隐患。就是OSS AccessId/AccessKey暴露在前端页面。可以随意拿到AccessId/AccessKey,这是非常不安全的做法。

这里的签名采用服务端方式生成,前端通过ajax获取。

在阿里云js直传文档范例里,签名生成只有java,php,python,go四种语言的例子,没有c#签名示例。这里用c#实现一个

其他语言的范例地址:https://help.aliyun.com/document_detail/31926.html?spm=5176.doc31923.6.625.Jpz3L5

示例用的Bucket名字为video,其中Bucket的三种访问控制,这里设置为公共读(匿名读,写操作需要身份验证)

技术分享

OSS PostObject接口介绍

 https://help.aliyun.com/document_detail/31988.html?spm=5176.7742976.2.2.uRq26Q

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

Policy表单域的示例  

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

Post policy中必须包含expiration和condtions。

 

计算Signature的具体流程为

  1. 创建一个 UTF-8 编码的 policy。
  2. 将 policy 进行 base64 编码,其值即为 policy 表单域该填入的值,将该值作为将要签名的字符串。
  3. 使用 AccessKeySecret 对要签名的字符串进行签名,签名方法与Head中签名的计算方法相同(将要签名的字符串替换为 policy 即可)。

Web直传服务端签名

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

 技术分享

技术分享

MVC控制器代码

 public class AliyunController : MyControllerBase
    {
        public string accessKeyId = System.Configuration.ConfigurationManager.AppSettings["aliyun_ak_id"];
        public string accessKeySecret = System.Configuration.ConfigurationManager.AppSettings["aliyun_ak_secret"];
        public string bucket = System.Configuration.ConfigurationManager.AppSettings["aliyun_bucket"];
        // GET: Aliyun
        public ContentResult GetPostObjectSignature(int courseId)
        {
            string host = "http://"+ bucket + ".oss-cn-shanghai.aliyuncs.com";

            const string endpoint = "http://oss-cn-shanghai.aliyuncs.com";

            var ossClient = new OssClient(endpoint, accessKeyId, accessKeySecret);

            var dir = "zhangsan/";//设置用户上传指定的前缀,必须以斜线结尾
            var expiration = DateTime.Now.AddMinutes(100);
            var policyConds = new PolicyConditions();
            policyConds.AddConditionItem(MatchMode.StartWith, PolicyConditions.CondKey, dir);//上传目录
            policyConds.AddConditionItem(PolicyConditions.CondContentLengthRange, 1, 1048576000);//允许上传的文件大小限制
            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"]]}
                */
            var base64Policy = Convert.ToBase64String(Encoding.UTF8.GetBytes(postPolicy));
            var signature = ComputeSignature(accessKeySecret, base64Policy);//生成签名

            TimeSpan ts = expiration - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            var expire = Convert.ToInt64(ts.TotalSeconds);

            Dictionary<string, object> response = new Dictionary<string, object>();
            response["accessid"] = accessKeyId;
            response["host"] = host;
            response["policy"] = base64Policy;
            response["signature"] = signature;
            response["expire"] = expire;
            //这个参数是设置用户上传指定的前缀
            response["dir"] = dir;
            return Content(JsonConvert.SerializeObject(response));
        }
}

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!