最新要闻
- 高考首日,考生乘坐“爱心送考车”奔赴考场
- 订购纸箱公司_订购纸箱
- 中国5月外汇储备31765.1亿美元 连续第7个月增加黄金储备
- 买字笔顺怎么读_买字笔顺
- 一到高考就下雨 究竟是不是错觉?专家:亚洲季风导致
- AI考生迎战高考语文!于丹评ChatGPT写的高考作文:毫无灵性和才情 世界快资讯
- 高考离谱榜上新:家长送孩子高考 竟把小女儿忘考场
- 《暗黑破坏神4》梅根福克斯宣传片:祝玩家在游戏中“死得其所”|当前简讯
- 世界热推荐:一箭26星新纪录!中科宇航力箭一号大型固体火箭发射圆满成功
- 15英寸MacBook Air先别买!首发价格太高 降价空间不小|环球今热点
- 商品期货收盘多数下跌,甲醇跌3%,纸浆、尿素、纯碱跌超2%_世界动态
- 环球今头条!宝宝脸上红疙瘩识别图片_宝宝脸上红疙瘩识别图
- 【世界独家】全国职工数字化应用技术技能大赛决赛在福州举行
- 宿便是什么意思_宿便的解释|全球动态
- 氢气还原氧化铁的化学方程式是什么_氢气还原氧化铁的化学方程式|快消息
- 焦点热讯:高考今日开跑,贝克汉姆拍视频用中文喊:“高考加油”
广告
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
NetCore服务器对接小程序直传阿里云OSS|即时看
(资料图)
NetCore服务器对接小程序直传阿里云OSS
问题描述:小程序只支持POST方式上传文件,阿里云生成上传链接只能为PUT上传。小程序得使用前端直传方式。本示例为服务器端签名直传并设置上传回调。
PolicyToken.cs
internal class PolicyToken{public string accessid { get; set; }public string policy { get; set; }public string signature { get; set; }public string dir { get; set; }public string host { get; set; }public string expire { get; set; }public string callback { get; set; }}
CallbackParm.cs
internal class CallbackParam{public string callbackUrl { get; set; }public string callbackBody { get; set; }public string callbackBodyType { get; set; }}
生成 PolicyToken
CallbackBody系统参数就不过多说明,详见上面的官方文档,主要说说自定义参数,在构造 Form 表单的参数时,参数名,可以任意命名,但是有两点要注意:
- 自定义参数的格式,必须是
${x:<占位符>}
,x:
一定不能少- 自定义参数的占位符,就是
${x:<占位符>}
部分,花括号内部的名称,必须全部小写,比如:可以是userName=${x:username}&Age=${x:age}
也可以是username=${x:username}&age=${x:age}
,总之,注意占位符全部小写就行了,参数名,按照任意命名方式都可以,回调接口内注意读取就行了- 可以不用自定义占位符,直接对参数进行赋值,比如:`username=张三&age=20
public string GetPolicyToken(string bucketName, string uploadDir, string callbackUrl, long expireTime) { //expireTime var expireDateTime = DateTime.Now.AddSeconds(expireTime); // example of policy //{ // "expiration": "2020-05-01T12:00:00.000Z", // "conditions": [ // ["content-length-range", 0, 1048576000] // ["starts-with", "$key", "user-dir-prefix/"] // ] //} //policy var policyConds = new PolicyConditions(); policyConds.AddConditionItem(PolicyConditions.CondContentLengthRange, 100, 1024 * 1024 * 400); // 指定key policyConds.AddConditionItem(MatchMode.Exact, PolicyConditions.CondKey, uploadDir); //policyConds.AddConditionItem(MatchMode.StartWith, PolicyConditions.CondKey, uploadDir); var policy = _ossClient.GeneratePostPolicy(expireDateTime, policyConds); var policy_base64 = EncodeBase64("utf-8", policy); var signature = ComputeSignature(_aliyunOSSConfig.AccessKeySecret, policy_base64); //callback var callback = new CallbackParam(); callback.callbackUrl = callbackUrl; callback.callbackBody = "filename=${object}&size=${size}&mimeType=${mimeType}"; callback.callbackBodyType = "application/x-www-form-urlencoded"; var callback_string = JsonConvert.SerializeObject(callback); var callback_string_base64 = EncodeBase64("utf-8", callback_string); var policyToken = new PolicyToken(); policyToken.accessid = _aliyunOSSConfig.AccessKeyId; policyToken.host = $"https://{bucketName}.{_aliyunOSSConfig.Host}"; policyToken.policy = policy_base64; policyToken.signature = signature; policyToken.expire = ToUnixTime(expireDateTime); policyToken.callback = callback_string_base64; policyToken.dir = uploadDir; return JsonConvert.SerializeObject(policyToken); } private static string ToUnixTime(DateTime dtime) { const long ticksOf1970 = 621355968000000000; var expires = ((dtime.ToUniversalTime().Ticks - ticksOf1970) / 10000000L) .ToString(CultureInfo.InvariantCulture); return expires; } private static string ComputeSignature(string key, string data) { using (var algorithm = new HMACSHA1()) { algorithm.Key = Encoding.UTF8.GetBytes(key.ToCharArray()); return Convert.ToBase64String( algorithm.ComputeHash(Encoding.UTF8.GetBytes(data.ToCharArray()))); } } private static string EncodeBase64(string code_type, string code) { string encode = ""; byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code); try { encode = Convert.ToBase64String(bytes); } catch { encode = code; } return encode; }
回调验签
验签步骤
- 获取
Authoriaztion
的值,进行Base64
解码,得到byte[]
。- 对
x-oss-pub-key-url
的值,进行Base64
解码,得到公钥的url
地址。- 校验公钥
url
地址,防止伪造,公钥地址为:
http://gosspublic.alicdn.com/
https://gosspublic.alicdn.com/
- 根据公钥
url
地址获取公钥内容。- 将
<请求路径>?<参数>\n
或<请求路径>\n
拼接,计算MD5
获取byte[]
(请求路径不包含Host
)。- 基于
RSA
,采用MD5
模型进行验签。- 将验证结果返回给OSS(OSS 仅接收 Json 格式的返回)。
- OSS 会将返回的内容直接返回给前端。
public async Task VerifySignature() { // Get the Authorization Base64 from Request var request = _httpContextAccessor.HttpContext.Request; if (!request.Headers.TryGetValue("Authorization", out var authInfo) || StringValues.IsNullOrEmpty(authInfo)) { return false; } // Decode the Authorization from Request var byteAuth = Convert.FromBase64String(authInfo); // Decode the URL of PublicKey if (!request.Headers.TryGetValue("x-oss-pub-key-url", out var tempPubKeyUrl) || StringValues.IsNullOrEmpty(tempPubKeyUrl)) { return false; } var bytePubKeyUrl = Convert.FromBase64String(tempPubKeyUrl.ToString()); var pubKeyUrl = Encoding.ASCII.GetString(bytePubKeyUrl); // 验证公钥域名 if (!pubKeyUrl.StartsWith("http://gosspublic.alicdn.com/", StringComparison.OrdinalIgnoreCase) && !pubKeyUrl.StartsWith("https://gosspublic.alicdn.com/", StringComparison.OrdinalIgnoreCase)) { return false; } // Get PublicKey from the URL ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate); using var client = _httpClientFactory.CreateClient(); var pubKey = await client.GetStringAsync(pubKeyUrl); var strPublicKeyContentBase64 = pubKey.Replace("-----BEGIN PUBLIC KEY-----\n", "").Replace("-----END PUBLIC KEY-----", "").Replace("\n", ""); var strPublicKeyContentXML = RSAPublicKeyString2XML(strPublicKeyContentBase64); // Generate the New Authorization String according to the HttpRequest var httpURL = request.Path.ToString() + request.QueryString.ToString(); // Read body var dictBody = new Dictionary(); if (request.HasFormContentType) { foreach (var item in request.Form) { dictBody.Add(item.Key, item.Value); } } var httpBody = string.Join("&", dictBody.Select(per => $"{per.Key.UrlEncode(true)}={per.Value.UrlEncode(true)}")); // StreamReader stream = new StreamReader(_httpContextAccessor.HttpContext.Request.Body); // var httpBody = await stream.ReadToEndAsync(); var strAuthSourceForMD5 = string.Empty; if (httpURL.Contains("?")) { var arrURL = httpURL.Split("?"); strAuthSourceForMD5 = string.Format("{0}?{1}\n{2}", System.Web.HttpUtility.UrlDecode(arrURL[0]), arrURL[1], httpBody); } else { strAuthSourceForMD5 = string.Format("{0}\n{1}", System.Web.HttpUtility.UrlDecode(httpURL), httpBody); } // MD5 hash bytes from the New Authorization String var byteAuthMD5 = ByteMD5Encrypt32(strAuthSourceForMD5); // Verify Signature using var RSA = new RSACryptoServiceProvider(); try { RSA.FromXmlString(strPublicKeyContentXML); } catch (ArgumentNullException e) { throw new ArgumentNullException(string.Format("VerifySignature Failed : RSADeformatter.VerifySignature get null argument : {0} .", e)); } catch (CryptographicException e) { throw new CryptographicException(string.Format("VerifySignature Failed : RSA.FromXmlString Exception : {0} .", e)); } RSAPKCS1SignatureDeformatter RSADeformatter = new RSAPKCS1SignatureDeformatter(RSA); RSADeformatter.SetHashAlgorithm("MD5"); var bVerifyResult = false; try { bVerifyResult = RSADeformatter.VerifySignature(byteAuthMD5, byteAuth); } catch (ArgumentNullException e) { throw new ArgumentNullException(string.Format("VerifySignature Failed : RSADeformatter.VerifySignature get null argument : {0} .", e)); } catch (CryptographicUnexpectedOperationException e) { throw new CryptographicUnexpectedOperationException(string.Format("VerifySignature Failed : RSADeformatter.VerifySignature Exception : {0} .", e)); } return bVerifyResult; } public static byte[] ByteMD5Encrypt32(string password) { string cl = password; using MD5 md5 = MD5.Create(); byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl)); return s; } public static string RSAPublicKeyString2XML(string publicKey) { RsaKeyParameters publicKeyParam = (RsaKeyParameters)PublicKeyFactory.CreateKey(Convert.FromBase64String(publicKey)); return string.Format("{0} {1} ", Convert.ToBase64String(publicKeyParam.Modulus.ToByteArrayUnsigned()), Convert.ToBase64String(publicKeyParam.Exponent.ToByteArrayUnsigned())); } public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; }
StringExtension.cs
public static string UrlEncode(this string content, bool needUpper = false) { if (string.IsNullOrEmpty(content)) { return string.Empty; } if (!needUpper) { return HttpUtility.UrlEncode(content); } var result = new StringBuilder(); foreach (var per in content) { var temp = HttpUtility.UrlEncode(per.ToString()); if (temp.Length > 1) { result.Append(temp.ToUpper()); continue; } result.Append(per); } return result.ToString(); }
链接:阿里云 OSS Web 直传/回调/回调签名验证(.NET/C#/Layui) - 简书 (jianshu.com)
关键词:
NetCore服务器对接小程序直传阿里云OSS|即时看
高考首日,考生乘坐“爱心送考车”奔赴考场
订购纸箱公司_订购纸箱
中国5月外汇储备31765.1亿美元 连续第7个月增加黄金储备
债市日报:6月7日
买字笔顺怎么读_买字笔顺
一到高考就下雨 究竟是不是错觉?专家:亚洲季风导致
AI考生迎战高考语文!于丹评ChatGPT写的高考作文:毫无灵性和才情 世界快资讯
高考离谱榜上新:家长送孩子高考 竟把小女儿忘考场
《暗黑破坏神4》梅根福克斯宣传片:祝玩家在游戏中“死得其所”|当前简讯
世界热推荐:一箭26星新纪录!中科宇航力箭一号大型固体火箭发射圆满成功
15英寸MacBook Air先别买!首发价格太高 降价空间不小|环球今热点
商品期货收盘多数下跌,甲醇跌3%,纸浆、尿素、纯碱跌超2%_世界动态
环球今头条!宝宝脸上红疙瘩识别图片_宝宝脸上红疙瘩识别图
世界看热讯:链家广州二手房数据 2023
数据驱动的教育创新:大数据在学校的应用_当前资讯
CentOS7 本地光盘镜像rpm包-今日热议
快资讯:DDL语句
slack 团队及个人工作学习的好帮手
天天观天下!土耳其里拉遭遇两年来最大单日抛售
【世界独家】全国职工数字化应用技术技能大赛决赛在福州举行
宿便是什么意思_宿便的解释|全球动态
氢气还原氧化铁的化学方程式是什么_氢气还原氧化铁的化学方程式|快消息
焦点热讯:高考今日开跑,贝克汉姆拍视频用中文喊:“高考加油”
闽清高考生速看!遗忘身份证不要慌
环球实时:高考防作弊磁弹枪亮相:可狙击黑飞无人机
“奔驰小G”正式上市 搭载2.0T四缸发动机 售价142.48万起 天天微头条
为Vision Pro做准备?苹果被曝收购AR初创公司Mira 世界球精选
环球速看:尴尬到家!RX 7600 eBay一周销量为零、RTX 4060 Ti只卖出一块
真心建议:拉完便便 一定要回头看一眼!
美原油交易策略:多空消息交替影响油价,关注EIA数据
吉林高龄补贴2023发放标准:2023吉林省各地区高龄补贴标准是多少?|看点
*ST金山(600396)6月7日主力资金净买入339.20万元
一天杀两白马!长春高新大跌超9%
阿里云 Serverless 容器服务全面升级:新增组件全托管、AI 镜像秒级拉取能力
微信dat文件转图片(jpg,png,gif) 当前快报
看点:港股午评:恒指涨0.97%报19285.1点,科网股普遍收涨
天天新消息丨2023吉网高考观察①丨逐光的你们,就是自己的光!
环球观点:日债市场流动性改善 多数期限品种收益率下行
当前消息!收评:创指跌1.61%续创年内新低 AI概念股走强、新能源赛道股回落
你过桥他爬桥、买个馒头排大队……网红打卡怎样才能不招人烦?
盛和资源(600392)6月7日主力资金净卖出1458.87万元_全球热文
一杯两用:佳适高颜值大容量大肚杯1300ML 19.9元
即时焦点:茅台卖咖啡可加料:12元1.8ml茅台酒 喝完不能开车
网友吐槽苹果Vision Pro头戴卖2.5万太贵 库克回应:物超所值
微软发掘AI“新用途”:搜索Chrome时BingChat打出推广-天天新要闻
一到高考就下雨 究竟是不是错觉?专家:亚洲季风导致 热门
固体饮料能预防疾病?江苏江阴消保委:属虚假宣传|世界头条
长沙会战的意义(长沙会战)_要闻
顶象发布《车企App安全研究白皮书》,剖析品牌汽车App的两大类风险
每日观察!GaussDB(DWS)查询过滤器原理与应用
全球热点!SQL Server 补丁理解及安装 内附完整版下载地址及sp1/2/3补丁
领导看了给你加薪!python +ddt+excel 一招鲜,接口自动化测试轻松搞定,测试报告惊艳四座!-全球独家
世界微速讯:平顶山市:连锁食品经营企业实现“一套材料、一次核查”
学哥学姐暖心寄语:拼搏吧高考少年
全球速读:西部证券:给予巨子生物买进的初始评级,目标价47.24港元。
【环球新视野】盘点高考各地第一个走出考场的考生:将平静面对接下来的考试
全球即时:无人车撞死小狗:系统已识别、还有安全员、就是不刹车!
第27次冲刺 高考钉子户梁实谈语文考试:不是很失败 应该能拿105分
当前热文:比亚迪高考作文押题成功!公关李云飞评论区被刷屏
俞敏洪建议高考完别对答案:正常饮食和睡眠
李凯丽是谁呀_李凯丽 中国女艺人
股权溢价转让怎么纳税
备战亚运!多支国家队来浙江集训
MySQL逻辑架构及执行过程
SQLYog使用教程
jenkins~权限控制 世界热推荐
一份配置轻松搞定表单渲染,配置式表单渲染器在袋鼠云的实现思路与实践
[Docker/K8S]Docker与K8S的区别
券商观点|定制家居行业专题研究:整家与整装战略落地,需求有望逐步改善
全球热讯:超图软件:公司与Unity有紧密的技术合作
聚焦:重大突破!华为发布首款全栈自主数据库GaussDB:真正属于中国人自己的数据库来了
1小时收费6.5元!共享单车悄然涨价超地铁:你还用吗?
宝马轿车被追尾 贬值损失能赔吗
环球视点!kp什么意思网络用语(网络上kp是什么意思)
滞困异星黎明MOTOR-FIGURE种子是什么|热点评
海力布石头图片真实
众星为高考学子加油打气 周冬雨被曝高考仅 286 分-前沿热点
Apache Solr 教程_编程入门自学教程_菜鸟教程-免费教程分享
世界消息!天元宠物:6月6日融资买入131.17万元,融资融券余额2873.89万元
公路交通工程专业承包资质机构_公路交通工程专业承包资质
我市公布海洋公益诉讼成果 发布海洋公益诉讼协同治理最佳方案、海洋公益诉讼十佳案例等|当前热文
猪的智商很高吗?_猪的智商高吗
晶升股份、唯捷创芯等16只科创板股融资余额增幅超10%_新资讯
2023年6月7日山东省二乙氨基乙醇价格最新行情预测|环球时快讯
男子花147万买保时捷提车2天就坏了!4S店:赔8000元代金券
全球看点:网传克扣供应商10%货款 长安汽车发声明:从未收到申诉函、已报案
珠峰获救女子不愿承担费用 律师建议起诉:农夫与蛇风气不可助长-世界焦点
天天热点评!685人晋级2023阿里巴巴全球数学竞赛决赛:清北、麻省理工高手云集
18只个股上午主力净流入超1亿元 华工科技居首 每日动态
【天天播资讯】甘肃省博物馆门票怎么预约(个人+团队)
完善养老保险体系 提高养老保障水平 短讯
讯息:南通和海牛难敌上海双雄,大连人爬坑!国安换帅吧,谢晖送斯坦利一程
涛涛车业:6月6日融资买入523.15万元,融资融券余额4265.74万元
当前观察:最新豆一期货价格行情查询(2023年6月7日)
全球关注:AI人工智能领域精美绘图模板分享
全球热讯:java HttpClient工具类
1万4千条生活小知识常识大全ACCESS\EXCEL数据库
要闻速递:【财经分析】短端利率定价基本合理 机构提示关注调整风险
世界新动态:开展12600余项减排项目 广东持续打好臭氧污染防治攻坚战