浏览器中生成 OSS 令牌 | Web Crypto API
笔者写文章的时候,都会把图片通过自己搭建的一个简单站点 https://imgbed.sugarat.top/ 把图片上传到各种云的对象存储服务(OSS)上。
然后通过CDN访问,保证图片有可靠的访问速度和质量。
本着尽可能简单,减少对后端依赖的原则,上传令牌是在本地(Node.js)生成并设置一个过期时间,在浏览器中直接粘贴,存放在 LocalStorage 中,过期就在本地重新生成一次就行。
但现在生成的时候也还有2个麻烦点:① 依赖 Node.js 环境 ② 关键的秘钥存储在本地文件中
本次迭代就是把这2个麻烦点解决掉!
生成原理
又拍云
参考文档:token 认证生成
简化成 JS 代码如下
// 基本配置
const operator = '账号'
const password = '密码'
const method = 'PUT' // 上传时用到的请求方法
const urlPrefix = 'bucketName/sourcePrefix' // 资源在OSS上的桶名称和公共路径前缀
const expire = Math.floor(Date.now() / 1000) + 3600 // 过期时间 1小时后过期
// 计算token
const token = base64(hmacSha1(MD5(password), `${method}&${urlPrefix}&${expire}`))
// 最终上传用到的请求头
const Authorization = `UPYUN ${operator}:${token}`
依赖的算法
- base64:将数据转换为 ASCII 字符串的编码
- HMAC_SHA-1:基于 SHA-1 哈希算法的消息认证码,用于验证消息的完整性和真实性
- MD5:哈希函数,用于生成数据的数字指纹
七牛云
参考文档:上传凭证,URL安全的Base64编码
简化成 JS 代码如下
// 基本配置
const accessKey = 'ACCESS_KEY'
const secretKey = 'SECRET_KEY'
const bucket = 'BUCKET_NAME' // OSS 桶名称
const expires = Math.floor(Date.now() / 1000) + 3600 // 过期时间 1小时后过期
const encodedFlags = base64ToUrlSafe(base64(JSON.stringify({
scope: bucket,
deadline: expires,
})))
const encodedSign = base64ToUrlSafe(base64(hmacSha1(secretKey, encodedFlags)))
// 最终上传用到的令牌
const uploadToken = `${accessKey}:${encodedSign}:${encodedFlags}`
其中 base64ToUrlSafe 是 “URL安全的Base64编码” 相关的方法
URL安全的Base64编码适用于以URL方式传递Base64编码结果的场景。该编码方式的基本过程是先将内容以Base64格式编码为字符串,然后检查该结果字符串,将字符串中的加号
+换成中划线-,并且将斜杠/换成下划线_。
// 实现如下
function base64ToUrlSafe(v: string) {
return v.replace(/\//g, '_').replace(/\+/g, '-')
}
其它依赖算法和又拍云基本一致 hmacSha1 和 base64。
加密方法的实现
这里分别介绍浏览器和 Node.js 环境下的简单实现。
前端浏览器侧实现
base64 和 HMAC_SHA-1 算法都有现成的实现,分别可以使用浏览器提供的 btoa 和 Crypto API。
function base64(value: string) {
return btoa(value)
}
HMAC_SHA-1
在阅读 MDN: Crypto API 文档时先可以看到 Crypto.subtle 的描述。
从字面意思不难看出就是我们需要的API。
从 HMAC 的例子中,就可以找到我们需要的关键信息:
关键代码如下
const encoder = new TextEncoder()
const encoded = encoder.encode(value)
const signature = await window.crypto.subtle.sign('HMAC', key, encoded)
其中 key 是我们需要的密钥,可以用 SubtleCrypto.importKey() 导入生成。
const encoder = new TextEncoder()
const key = await window.crypto.subtle.importKey(
'raw',
encoder.encode(password), // password 是我们的密钥
{ name: 'HMAC', hash: { name: 'SHA-1' } },
false,
['sign'],
)
最终我们的方法实现如下。
async function hmacSha1(key: string, value: string) {
const encoder = new TextEncoder()
const cryptoKey = await window.crypto.subtle.importKey(
'raw',
encoder.encode(key),
{ name: 'HMAC', hash: { name: 'SHA-1' } },
false,
['sign'],
)
const data = encoder.encode(value)
const hashBuffer = await window.crypto.subtle.sign('HMAC', cryptoKey, data)
return arrayBufferToBase64(hashBuffer) // 返回 base64 格式的结果
}
function arrayBufferToBase64(buffer: ArrayBuffer) {
const uint8Array = new Uint8Array(buffer)
const base64String = String.fromCharCode(...uint8Array)
return btoa(base64String)
}
MD5
MD5 可以使用 开源库 spark-md5
import SparkMD5 from 'spark-md5'
export function MD5(str: string): string {
return SparkMD5.hash(str)
}
Node.js 实现
Node.js 环境下,可以直接使用内置 node:crypto 模块提供的各种加密算法,十分方便。
HMAC_SHA-1
import crypto from 'crypto'
function hmacSha1(key: string, value: string) {
const hmac = crypto.createHmac('sha1', key)
hmac.update(value) // 设置用于计算校验值的字符串
return hmac.digest('base64') // 计算校验值,并按照 base64 返回
}
MD5
import crypto from 'crypto'
function MD5(value: string) {
const md5 = crypto.createHash('md5')
md5.update(value) // 设置用于计算 MD5 值的字符串
return md5.digest('hex') // 计算 MD5 值,并直接以十六进制字符串返回
}
安全问题
针对存储 账号&密码 等敏感信息的可以使用浏览器提供的账号密码管理能力存储。
例如 Chrome 中提供的 PasswordCredential 相关API。
调用后就可以唤起存储的弹窗。
最后
总结一下:浏览器中也可以使用window.crypto提供的 API,完成常用的加密算法调用,同时也可以在 Web Worker 中使用,可以有效提升性能。
当前这一版图床,应该也还不是最终版,后续计划将部分管理功能以某种可能得形式完成纯静态的支持。
欢迎评论区交流想法&意见
浏览器中生成 OSS 令牌 | Web Crypto API的更多相关文章
- 内卷时代下的前端技术-使用JavaScript在浏览器中生成PDF文档
背景 在计量领域中,计量检定是一种重要形式,主要用于评定计量器具的计量性能,确定其量值是否准确一致,实现手段包括计量检验.出具检定证书和加封盖印等. 在检定证书这一环节,存在一个难点,就是无法在线预览 ...
- 关于点击ztree的节点将页面生成到easyui的新增选项卡(easyui-tabs)时,总是在浏览器中生成一个新的页面的问题
最近的项目中用到了easyui,还有ztree菜单.在这里将我遇到的一些问题写出来算是做个笔记吧. 这是我头一次在博客园里分享代码,我的处女作,写的不好的地方还望各位见谅! 由于很久没有写过前台的东西 ...
- python中生成JWK(json web token)
#需要安装pyjwt import jwt import time # 使用 sanic 作为restful api 框架 def create_token(request): grant_type ...
- VS2010中生成遇到的 web.config 问题
1. 错误:无法在此路径使用此配置节.当站点管理员使用继承的配置文件中的 <location allowOverride="false"> 锁定对此节的访问时会出现 ...
- Web Animations API (JS动画利器)
原文地址:→传送门 写在前面 之前学习了CSS animation/setTimeout/setInterval/requestAnimationFrame等,这些都可以用在某种场景下的小动画,也可以 ...
- Web Storage API的介绍和使用
目录 简介 浏览器的本地存储技术 Web Storage相关接口 浏览器兼容性 隐身模式 使用Web Storage API 总结 简介 Web Storage为浏览器提供了方便的key value存 ...
- ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程
ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程 翻译自:地址 在今年年初,我整理了有关将JWT身份验证与ASP.NET Core Web API和Angular一起使用的详 ...
- 第十一章:WEB浏览器中的javascript
客户端javascript涵盖在本系列的第二部分第10章,主要讲解javascript是如何在web浏览器中实现的,这些章节介绍了大量的脚本宿主对象,这些对象可以表示浏览器窗口.文档树的内容.这些章节 ...
- JavaScript权威指南--WEB浏览器中的javascript
知识要点 1.客户端javascript window对象是所有客户端javascript特性和API的主要接入点.它表示web浏览器的一个窗口或窗体,并且可以用window表示来引用它.window ...
- HTML5 Web Speech API 结合Ext实现浏览器语音识别以及输入
简介 Web Speech API是HTML5技术中的一个提供原生语音识别技术的API,Google Chrome在25版之后开始支持Web Speech API,Google也提供了一个 ...
随机推荐
- 信奥生(OIER)请看,包囊初赛复赛全真模拟赛!
luogu 动态追踪! 唠唠嗑 感谢 tyw 代理团主对比赛的贡献,但是由于我和 tyw 的关系紧张,tyw 取消了我和她的一切合作.CTFPC-3rd 的出题.宣传工作都交到了我手上,我这次亚历山大 ...
- 【Vue】分组类型排名查询功能
一.书接上回: https://www.cnblogs.com/mindzone/p/17749725.html 这个效果被否决了,产品要求一定要UI的来,UI效果如图: 按人为主体的时候,固定有4个 ...
- 【转载】 PID原理与参数调试
原文地址: http://m.elecfans.com/article/1153309.html --------------------------------------------------- ...
- 一个域名可以对应多个IP吗,一个IP可以对应多个域名吗?
本文谈两个问题:一个域名可以对应多个IP吗,一个IP可以对应多个域名吗? 问题1:一个IP可以对应多个域名吗? 因为域名都是由各个域名供应商提供的,我们可以在不同的域名供应商那里买不同的域名,然后把这 ...
- bazel编译报错:absl/base/policy_checks.h:79:2: error: #error "C++ versions less than C++14 are not supported."
使用bazel编译一个软件时报错,报错的信息为: absl/base/policy_checks.h:79:2: error: #error "C++ versions less than ...
- 备忘 : 使用VS2022后,发现C盘空间越来越少怎么办?
背景 自从安装完VS2022后,感觉C盘容量肉眼可见的降低.之前2019并没有产生如此严重的情况.后面查看发现,Designer/Cache缓存的数据很大(截图是已经删除过的) 解决方案 在平台的反馈 ...
- 用户案例 | 蜀海供应链基于 Apache DolphinScheduler 的数据表血缘探索与跨大版本升级经验
导读 蜀海供应链是集销售.研发.采购.生产.品保.仓储.运输.信息.金融为一体的餐饮供应链服务企业.2021年初,蜀海信息技术中心大数据技术研发团队开始测试用DolphinScheduler作为数据中 ...
- 实操教程 | 触发器实现 Apache DolphinScheduler 失败钉钉自动告警
作者 | sqlboy-yuzhenc 背景介绍 在实际应用中,我们经常需要将特定的任务通知给特定的人,虽然 Apache DolphinScheduler 在安全中心提供了告警组和告警实例,但是配置 ...
- 2023 CCPC 桂林题解
gym H. Sweet Sugar 一个经典贪心是从下到上,如果子树 \(u\) 剩下的部分(一定包含 \(u\))包含合法连通块,那么这个连通块给答案贡献 \(1\),切断 \(u\) 与 \(f ...
- celery僵死导致jumpserver提示 连接WebSocket失败
celery僵死导致jumpserver提示连接WebSocket失败 Celery的任务监控位于堡垒机 "作业中心"下的"任务监控" 中,点击打开新的页面如下 ...