aliyun oss js直传且使用服务器端生成签名
采用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的具体流程为:
- 创建一个 UTF-8 编码的 policy。
- 将 policy 进行 base64 编码,其值即为 policy 表单域该填入的值,将该值作为将要签名的字符串。
- 使用 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)); } }