浏览器中生成 OSS 令牌 | Web Crypto API

简介: 浏览器中生成 OSS 令牌 | Web Crypto API

笔者写文章的时候,都会把图片通过自己搭建的一个简单站点 [box.veshenzhen.com)/ 把图片上传到各种云的对象存储服务(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 代码如下
[box.liyumenhotel.com)
[box.hotins-sh.com)
[box.wuyejie.com)
// 基本配置
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。

调用后就可以唤起存储的弹窗。

最后

总结一下:浏览器中也可以使用[box.zyxingsheng.com)提供的 API,完成常用的加密算法调用,同时也可以在 Web Worker 中使用,可以有效提升性能。

当前这一版图床,应该也还不是最终版,后续计划将部分管理功能以某种可能得形式完成纯静态的支持。

欢迎评论区交流想法&意见

相关文章
|
24天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
16天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
20天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2577 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
18天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
3天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
2天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
163 2
|
20天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1576 16
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
22天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
977 14
|
4天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
221 2
|
17天前
|
人工智能 开发框架 Java
重磅发布!AI 驱动的 Java 开发框架:Spring AI Alibaba
随着生成式 AI 的快速发展,基于 AI 开发框架构建 AI 应用的诉求迅速增长,涌现出了包括 LangChain、LlamaIndex 等开发框架,但大部分框架只提供了 Python 语言的实现。但这些开发框架对于国内习惯了 Spring 开发范式的 Java 开发者而言,并非十分友好和丝滑。因此,我们基于 Spring AI 发布并快速演进 Spring AI Alibaba,通过提供一种方便的 API 抽象,帮助 Java 开发者简化 AI 应用的开发。同时,提供了完整的开源配套,包括可观测、网关、消息队列、配置中心等。
734 9