当前仓库属于暂停状态,部分功能使用受限,详情请查阅 仓库状态说明
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
wssql.js 5.83 KB
一键复制 编辑 原始数据 按行查看 历史
judgeou 提交于 2017-02-04 16:38 . init
// import Promise from 'bluebird'
import log from './logger'
const crypto = window.crypto
const subtle = crypto.subtle
const location = window.location
const textEncoder = new window.TextEncoder('utf-8')
const workQueue = [] // 暂存等待的任务
const cbArray = []
// 数据库事务级别
const TransactionLevel = {
READ_UNCOMMITTED: 1,
READ_COMMITTED: 2,
REPEATABLE_READ: 4,
SERIALIZABLE: 8
}
let tokens // 每次请求都要使用的令牌
let aesKey // AES加密的密钥
let hmacKey // hmac摘要算法密钥
let ws // websocket连接
kiss().then((ciphers) => {
aesKey = ciphers[0]
hmacKey = ciphers[1]
workQueue.forEach(item => {
item()
})
workQueue.length = 0
}).catch(log.error)
// 进行密钥协商
function kiss () {
return new Promise((resolve, reject) => {
subtle.generateKey({
name: 'ECDH',
namedCurve: 'P-256'
}, false, ['deriveKey']).then(key => {
subtle.exportKey('spki', key.publicKey).then(keydata => {
const data = new Uint8Array(keydata)
const data64 = window.btoa(String.fromCharCode.apply(null, data))
const host = (process.env.NODE_ENV === 'development') ? `${location.hostname}:8080` : location.host
const ai = cbArray.push(data => {
tokens = data.tokens
const pkBuffer = Uint8Array.from(window.atob(data.pk), c => c.charCodeAt(0)).buffer
subtle.importKey('spki', pkBuffer, { name: 'ECDH', namedCurve: 'P-256' }, false, []).then(pk => {
const encrypters = [
subtle.deriveKey({
name: 'ECDH',
public: pk
}, key.privateKey, {
name: 'AES-GCM',
length: 128
}, false, ['encrypt']),
subtle.deriveKey({
name: 'ECDH',
public: pk
}, key.privateKey, {
name: 'HMAC',
hash: { name: 'SHA-256' },
length: 256
}, false, ['sign'])
]
Promise.all(encrypters).then(resolve)
})
}) - 1
const wsurl = `ws://${host}/lover?pk=${encodeURIComponent(data64)}&ai=${ai}`
ws = new window.WebSocket(wsurl)
ws.onmessage = wsHandler
})
})
})
}
// websocket消息的集中处理处
function wsHandler (e) {
const data = JSON.parse(e.data)
log.debug(data)
cbArray[data.ai](data)
cbArray[data.ai] = null
}
function string2buffer (str) {
return textEncoder.encode(str).buffer
}
function buffer2base64 (buffer) {
buffer = new Uint8Array(buffer)
let binary = ''
let len = buffer.byteLength
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(buffer[i])
}
return window.btoa(binary)
}
function base642buffer (base64) {
return Uint8Array.from(window.atob(base64), c => c.charCodeAt(0))
}
function mergeBuffer (b1, b2) {
const ba = new Uint8Array(b1.byteLength + b2.byteLength)
ba.set(new Uint8Array(b1))
ba.set(new Uint8Array(b2), b1.byteLength)
return ba.buffer
}
function req (resolve, reject, action, msg) {
// 开始用AES进行加密
const iv = crypto.getRandomValues(new Uint8Array(12)).buffer
const sqlBuffer = string2buffer(msg)
subtle.encrypt({
name: 'AES-GCM',
iv,
tagLength: 128
}, aesKey, sqlBuffer).then(encBuffer => {
const token = tokens.pop()
if (token === undefined) {
reject(Error('too many request'))
return
}
const concatBuffer = mergeBuffer(encBuffer, base642buffer(token))
subtle.sign({
name: 'HMAC'
}, hmacKey, concatBuffer).then(hashBuffer => {
const hash64 = buffer2base64(hashBuffer)
const enc64 = buffer2base64(encBuffer)
const iv64 = buffer2base64(iv)
const ai = cbArray.push(res => {
tokens.push(res.token)
resolve(res.data)
}) - 1
ws.send(JSON.stringify({
ai,
action,
iv: iv64,
s: enc64,
hash: hash64,
token
}))
})
})
}
function exec (param, action) {
return new Promise((resolve, reject) => {
log.debug(param, '#2980b9')
if (aesKey && hmacKey) {
req(resolve, reject, action, param)
} else {
workQueue.push(() => {
req(resolve, reject, action, param)
}) // 密钥尚未协商完毕,推入队列,等待密钥完毕后一并执行
}
})
}
/**
* select - 查询
*
* @param {String} sql sql语句
* @param {Integer} tranId 事务id
* @return {Promise} 返回的数据
*/
function select (sql, tranId) {
const json = JSON.stringify({
sql,
tranId
})
return exec(json, 'select')
}
/**
* page - 分页查询
*
* @param {String} sql sql语句
* @param {Integer} page 当前页
* @param {Integer} rows 每页行数
* @return {Promise} 分页数据对象
*/
function page (sql, page, rows) {
const json = JSON.stringify({
sql,
page,
rows
})
return exec(json, 'page')
}
/**
* tran - 开始一个事务
*
* @param {TransactionLevel} level 事务级别
* @return {Promise} tranId 事物id
*/
function tran (level) {
const json = JSON.stringify({
level
})
return exec(json, 'tran')
}
/**
* commit - 提交事务
*
* @param {Integer} tranId 事务Id
* @return {Promise} 是否成功
*/
function commit (tranId) {
const json = JSON.stringify({
tranId
})
return exec(json, 'commit')
}
/**
* rollback - 回滚事务
*
* @param {Integer} tranId 事务Id
* @return {Promise} 是否成功
*/
function rollback (tranId) {
const json = JSON.stringify({
tranId
})
return exec(json, 'rollback')
}
/**
* update - 执行update
*
* @param {String} sql sql语句
* @param {Integer} tranId 事务Id
* @return {Promise}
*
*/
function update (sql, tranId) {
const json = JSON.stringify({
sql,
tranId
})
return exec(json, 'update')
}
export {
exec,
update,
page,
TransactionLevel,
select,
tran,
commit,
rollback
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化