笔者写文章的时候,都会把图片通过自己搭建的一个简单站点 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. java+mysql+tomcat环境变量配置(windows版)

    jdk8(本人用的jdk8) 系统变量->新建:{JAVA_HOME=[JDK安装目录]} 系统变量->PATH:头部追加%JAVA_HOME%\bin;%JAVA_HOME%\jre\b ...

  2. 什么是spring.factories,引入未知模块报错如何解决

    对于maven中引入其他外部包加入容器的过程,需要用到spring.factories spring.factories的作用:将自动配置类与对应的配置类集中在一起,方便springboot自动装配, ...

  3. 【Java】Map 映射接口 概述

    Map 映射接口 概述 Map是一个双列数据,存储K-V类型的数据 JDK1.2 - HashMap 是目前Map的主要实现类 JDK1.2 线程不安全的,效率高,可存储null的key和value ...

  4. 【Java】Enumeration Class 枚举类

    枚举类 enum 对象是有限的确定的.属于类的(静态的) 适合定义一组常量 例如固定的一些事物: - 季节 - 性别 - 状态 自定义枚举类的使用 public class EnumerationTe ...

  5. 【Scala】02 循环

    1.支持集合直接作为循环体的条件: // - - - - 支持集合遍历 - - - - var arr = Array(10, 20, 30) var arr2 = List(10, 20, 30) ...

  6. 【SQL】列转字符串函数

    还是这个需求 主界面的列表表格是直接在后台用SQL查出来的 public String getQuerySql(ElemBean condition, List<Object> param ...

  7. JDBC详解学习笔记

    JDBC简介 架构时--没有什么是加一层解决不了的,如果有,就再加一层. 如tomcat集群上面的Nginx,Nginx集群上面的LVS. JDBC是数据库驱动的接口规范,是SUN公司未来简化开发人员 ...

  8. Webots —— 好用的人形机器人仿真平台

    相关: https://cyberbotics.com/doc/guide/tutorials 下载地址: https://github.com/cyberbotics/webots/releases ...

  9. 讲师招募 | Apache SeaTunnel Meetup等你来秀!

    2024年第三季度已经悄然开启,猛回头才发现今年的时日竟然已经过半!这半年又是在忙忙碌碌中度过,好在看着社区发展年中汇总的一串串数字,似乎都在预示着社区将在一条正确的轨道上,朝着好的方向继续发展.但又 ...

  10. 2022年第一天,体验了一把wan(皖)式服务

    在新的一年到来之际, 一口君首先祝各位粉丝朋友新年快乐! 心想事成! 事业顺利! 阖家欢乐! 财源广进! 2022年的第一天,一口君带着家人去了躺马鞍山,享受了一下马鞍山的洗浴. 马鞍山桑拿虽然比不上 ...