|
@@ -0,0 +1,166 @@
|
|
|
|
+class DecryptIframe {
|
|
|
|
+ constructor() {
|
|
|
|
+ this.createIframe()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ iframeOrigin = 'https://jybx2-webtest.jydev.jianyu360.com'
|
|
|
|
+ // iframeOrigin = 'http://localhost'
|
|
|
|
+ iframePath = '/page_big_pc/decrypt-js.html'
|
|
|
|
+ iframeEl = null // iframe的dom引用
|
|
|
|
+ iframeName = '' // iframe的name
|
|
|
|
+ iframeReady = false // 子页面是否初始化完成
|
|
|
|
+
|
|
|
|
+ taskList = [] // 任务队列,当ready=false时候,操作postMessage的回调放在列表中等待调用
|
|
|
|
+
|
|
|
|
+ receiveMap = {}
|
|
|
|
+
|
|
|
|
+ // doDecrypt解密函数promise回调缓存
|
|
|
|
+ _cacheMessagePromiseMap = {
|
|
|
|
+ // key: {
|
|
|
|
+ // resolve,
|
|
|
|
+ // reject
|
|
|
|
+ // }
|
|
|
|
+ }
|
|
|
|
+ _cacheWaitingReadyPromise = {
|
|
|
|
+ // resolve,
|
|
|
|
+ // reject
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ get iframeUrl() {
|
|
|
|
+ return `${this.iframeOrigin}${this.iframePath}`
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ createIframe() {
|
|
|
|
+ const iframe = document.createElement('iframe')
|
|
|
|
+ const name = `jianyu_${Date.now()}`
|
|
|
|
+ iframe.name = name
|
|
|
|
+ iframe.src = this.iframeUrl
|
|
|
|
+ iframe.style.display = 'none'
|
|
|
|
+ this.iframeName = name
|
|
|
|
+ this.iframeEl = iframe
|
|
|
|
+ document.body.append(iframe)
|
|
|
|
+
|
|
|
|
+ this.initEvents()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ getRandomString(len = 8) {
|
|
|
|
+ let randomString = ''
|
|
|
|
+ if (len) {
|
|
|
|
+ /** 默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1 **/
|
|
|
|
+ const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
|
|
|
|
+ const maxPos = $chars.length
|
|
|
|
+ for (let i = 0; i < len; i++) {
|
|
|
|
+ randomString += $chars.charAt(Math.floor(Math.random() * maxPos))
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ // Math.random() 生成随机数字, eg: 0.123456
|
|
|
|
+ // .toString(36) 转化成36进制 : "0.4fzyo82mvyr"
|
|
|
|
+ // .substring(2) 去掉前面两位 : "yo82mvyr"
|
|
|
|
+ // .slice(-8) 截取最后八位 : "yo82mvyr"
|
|
|
|
+ randomString = Math.random().toString(36).substring(2)
|
|
|
|
+ }
|
|
|
|
+ return randomString
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ createPostMessageKey() {
|
|
|
|
+ return `${this.getRandomString()}_${this.iframeName}`
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async doDecrypt(base64Key, cipherText) {
|
|
|
|
+ if (!this.iframeReady) {
|
|
|
|
+ await this.waitIframeReady()
|
|
|
|
+ }
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
+ const id = this.createPostMessageKey()
|
|
|
|
+ this.sendMessage({
|
|
|
|
+ id,
|
|
|
|
+ base64Key,
|
|
|
|
+ cipherText
|
|
|
|
+ })
|
|
|
|
+ this._cacheMessagePromiseMap[id] = {
|
|
|
|
+ resolve,
|
|
|
|
+ reject
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ async waitIframeReady() {
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
+ if (this.iframeReady) {
|
|
|
|
+ resolve()
|
|
|
|
+ } else {
|
|
|
|
+ this._cacheWaitingReadyPromise = {
|
|
|
|
+ resolve,
|
|
|
|
+ reject
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ initEvents() {
|
|
|
|
+ // load
|
|
|
|
+ const iframe = this.iframeEl
|
|
|
|
+ iframe.addEventListener('load', () => {
|
|
|
|
+ // iframe 中的 JavaScript 已经加载完成
|
|
|
|
+ this.iframeReady = true
|
|
|
|
+ if (this._cacheWaitingReadyPromise) {
|
|
|
|
+ this._cacheWaitingReadyPromise.resolve()
|
|
|
|
+ }
|
|
|
|
+ console.log('iframe JavaScript loaded!');
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ const onMessage = e => {
|
|
|
|
+ const id = e.data.id
|
|
|
|
+ if (e.data.type !== 'after-decrypt') {
|
|
|
|
+ if (this._cacheMessagePromiseMap[id]) {
|
|
|
|
+ this._cacheMessagePromiseMap[id].reject()
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ if (window === e.source) {
|
|
|
|
+ if (this._cacheMessagePromiseMap[id]) {
|
|
|
|
+ this._cacheMessagePromiseMap[id].reject()
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ const result = e.data
|
|
|
|
+ if (this._cacheMessagePromiseMap[id]) {
|
|
|
|
+ this._cacheMessagePromiseMap[id].resolve(result)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ window.removeEventListener('message', onMessage)
|
|
|
|
+ // 接收解密后的结果
|
|
|
|
+ window.addEventListener('message', onMessage)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sendMessage(payload = {}) {
|
|
|
|
+ const p = {
|
|
|
|
+ ...payload,
|
|
|
|
+ fromOrigin: location.origin,
|
|
|
|
+ type: 'decrypt'
|
|
|
|
+ }
|
|
|
|
+ const targetOrigin = this.iframeOrigin
|
|
|
|
+ const win = window.frames[this.iframeName]
|
|
|
|
+ win.postMessage(p, targetOrigin)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function SingleWrapper(cons) {
|
|
|
|
+ // 排除非函数与箭头函数
|
|
|
|
+ if (!(cons instanceof Function) || !cons.prototype) {
|
|
|
|
+ throw new Error('不是合法的构造函数')
|
|
|
|
+ }
|
|
|
|
+ var instance
|
|
|
|
+ return function () {
|
|
|
|
+ if (!instance) {
|
|
|
|
+ instance = new cons()
|
|
|
|
+ }
|
|
|
|
+ return instance
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const SingleDecryptIframe = SingleWrapper(DecryptIframe)
|
|
|
|
+
|
|
|
|
+export function createDecryptIframe () {
|
|
|
|
+ return new SingleDecryptIframe()
|
|
|
|
+}
|