笔者写文章的时候,都会把图片通过自己搭建的一个简单站点 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, '-')
}

其它依赖算法和又拍云基本一致 hmacSha1base64

加密方法的实现

这里分别介绍浏览器和 Node.js 环境下的简单实现。

前端浏览器侧实现

base64 和 HMAC_SHA-1 算法都有现成的实现,分别可以使用浏览器提供的 btoaCrypto 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的更多相关文章

  1. 内卷时代下的前端技术-使用JavaScript在浏览器中生成PDF文档

    背景 在计量领域中,计量检定是一种重要形式,主要用于评定计量器具的计量性能,确定其量值是否准确一致,实现手段包括计量检验.出具检定证书和加封盖印等. 在检定证书这一环节,存在一个难点,就是无法在线预览 ...

  2. 关于点击ztree的节点将页面生成到easyui的新增选项卡(easyui-tabs)时,总是在浏览器中生成一个新的页面的问题

    最近的项目中用到了easyui,还有ztree菜单.在这里将我遇到的一些问题写出来算是做个笔记吧. 这是我头一次在博客园里分享代码,我的处女作,写的不好的地方还望各位见谅! 由于很久没有写过前台的东西 ...

  3. python中生成JWK(json web token)

    #需要安装pyjwt import jwt import time # 使用 sanic 作为restful api 框架 def create_token(request): grant_type ...

  4. VS2010中生成遇到的 web.config 问题

    1. 错误:无法在此路径使用此配置节.当站点管理员使用继承的配置文件中的  <location allowOverride="false">  锁定对此节的访问时会出现 ...

  5. Web Animations API (JS动画利器)

    原文地址:→传送门 写在前面 之前学习了CSS animation/setTimeout/setInterval/requestAnimationFrame等,这些都可以用在某种场景下的小动画,也可以 ...

  6. Web Storage API的介绍和使用

    目录 简介 浏览器的本地存储技术 Web Storage相关接口 浏览器兼容性 隐身模式 使用Web Storage API 总结 简介 Web Storage为浏览器提供了方便的key value存 ...

  7. ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程

    ASP.NET Core Web API中带有刷新令牌的JWT身份验证流程 翻译自:地址 在今年年初,我整理了有关将JWT身份验证与ASP.NET Core Web API和Angular一起使用的详 ...

  8. 第十一章:WEB浏览器中的javascript

    客户端javascript涵盖在本系列的第二部分第10章,主要讲解javascript是如何在web浏览器中实现的,这些章节介绍了大量的脚本宿主对象,这些对象可以表示浏览器窗口.文档树的内容.这些章节 ...

  9. JavaScript权威指南--WEB浏览器中的javascript

    知识要点 1.客户端javascript window对象是所有客户端javascript特性和API的主要接入点.它表示web浏览器的一个窗口或窗体,并且可以用window表示来引用它.window ...

  10. HTML5 Web Speech API 结合Ext实现浏览器语音识别以及输入

    简介      Web Speech API是HTML5技术中的一个提供原生语音识别技术的API,Google Chrome在25版之后开始支持Web Speech API,Google也提供了一个 ...

随机推荐

  1. css 蛇形排序

    先看效果 需求: 一个[ 4  * ?]的网格布局,奇数行 布局 从左往右,偶数行 布局 从右往左. 思路1: js将数组按4个每份进行分割,将偶数份进行反向,然后再将分割后的数据,重新组装.( 太麻 ...

  2. 【WSDL】01 JAX-WS 入门案例

    去年这个时候工作遇见时暂时总结的笔记: https://www.cnblogs.com/mindzone/p/14777493.html 当时也不是很清楚,直到最近前同事又遇上了这项技术, 除了WSD ...

  3. 【Hibernate】05 缓存与MySQL事务隔离

    Cache 什么是缓存? 数据存储到数据库,是从内存中以流的方式写进[输出]到数据库,其效率并不是很高 - 所以在内存中暂存一部分数据,可以不以流的方式读取,效率是非常高的[相对于流来说] Hiber ...

  4. 【IDEA】DEBUG调试问题

    不要将断点打在方法的声明上: 会有一个菱形标志,在标记之后运行DEBUG模式会跑不起来 查看所有的断点标记: 在这里直接找到所有标记位置,弄掉就会跑起来了

  5. URDF使用语法【万字解析赶紧码住】 —— 机器人统一描述文件格式(Unified Robot Description Format)

    原文地址: https://zhuanlan.zhihu.com/p/665269288 具体内容略,请参照原文.

  6. 【转载】 关于tf.stop_gradient的使用及理解

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u013745804/article/de ...

  7. 解决GitHub不显示图片问题——GitHub图片显示失败

    在Github上打不开图片是一个极为常见的事情,出现这样的问题的原因就是我们的主机无法正确解析图片所在主机域名对应的IP地址,下面给出一个在本地主机(window10)上使用ping命令解析目标主机域 ...

  8. C# 反射以及实际场景使用

    1 什么是反射 首先要复习一下C#的编译过程,可以解释为下图 其中dll/exe中,包括元数据(metadata)和IL(中间语言Intermediate Language) 另外还出现的其他名词:C ...

  9. 这是DDD建模最难的部分(其实很简单)

      本文书接上回<为了落地DDD,我是这样"PUA"大家的> ,欢迎关注我的同名公众号. https://mp.weixin.qq.com/s/DjC0FSWY1bgJ ...

  10. Next.js 中为什么 App Router 可能是未来,但 Pages Router 仍然重要?

    Next.js 作为一个强大的 React 框架,为开发者提供了两种路由系统:App Router 和 Pages Router.这两种路由系统各有特色,适用于不同的场景.本文将深入探讨这两种路由系统 ...