oss上传秘钥加密

master
yujialong 4 months ago
parent 4d1f77b168
commit 8351ac7190
  1. 10
      package-lock.json
  2. 2
      package.json
  3. 1
      src/api/index.js
  4. 46
      src/components/upload/config.js
  5. 42
      src/components/upload/index.vue
  6. 49
      src/components/upload/upload.js
  7. 241
      src/layouts/home/index.vue

10
package-lock.json generated

@ -3823,6 +3823,11 @@
"randomfill": "^1.0.3" "randomfill": "^1.0.3"
} }
}, },
"crypto-js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
},
"css": { "css": {
"version": "2.2.4", "version": "2.2.4",
"resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz",
@ -9345,6 +9350,11 @@
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
}, },
"jsencrypt": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/jsencrypt/-/jsencrypt-3.3.2.tgz",
"integrity": "sha512-arQR1R1ESGdAxY7ZheWr12wCaF2yF47v5qpB76TtV64H1pyGudk9Hvw8Y9tb/FiTIaaTRUyaSnm5T/Y53Ghm/A=="
},
"jsesc": { "jsesc": {
"version": "2.5.2", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",

@ -12,6 +12,7 @@
"ali-oss": "^6.18.1", "ali-oss": "^6.18.1",
"axios": "^0.18.0", "axios": "^0.18.0",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"crypto-js": "^4.2.0",
"decimal.js": "^10.4.3", "decimal.js": "^10.4.3",
"echarts": "^4.8.0", "echarts": "^4.8.0",
"element-theme": "^2.0.1", "element-theme": "^2.0.1",
@ -19,6 +20,7 @@
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"image-webpack-loader": "^8.1.0", "image-webpack-loader": "^8.1.0",
"js-cookie": "^2.2.1", "js-cookie": "^2.2.1",
"jsencrypt": "^3.3.2",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"mavon-editor": "^2.10.4", "mavon-editor": "^2.10.4",
"postcss-px2rem": "^0.3.0", "postcss-px2rem": "^0.3.0",

@ -13,6 +13,7 @@ export default {
refreshPageNotification: `nakadai/message/refreshPageNotification`, refreshPageNotification: `nakadai/message/refreshPageNotification`,
getCurrentTime: `competition/competition/management/getCurrentTime`, getCurrentTime: `competition/competition/management/getCurrentTime`,
heartbeatDetection: `nakadai/message/heartbeatDetection`, heartbeatDetection: `nakadai/message/heartbeatDetection`,
encrypt: `nakadai/data/encrypt`,
getPlayAuth: `oss/manage/getPlayAuth`, // 获取播放凭证 getPlayAuth: `oss/manage/getPlayAuth`, // 获取播放凭证

@ -1,15 +1,41 @@
/** /**
* 阿里云oss配置 * 阿里云oss配置
* */ * */
import { get } from '@/plugins/requests/index.js'
import api from '@/api'
import CryptoJS from 'crypto-js'
import JSEncrypt from 'jsencrypt'
export default { const A = (key, encryptedData) => {
// oss账号信息 const keyHex = CryptoJS.enc.Base64.parse(key)
config: { const decrypted = CryptoJS.AES.decrypt(encryptedData, keyHex, {
region: 'oss-cn-shenzhen', mode: CryptoJS.mode.ECB,
accessKeyId: 'LTAI4FzqQHnk4rozqLZ8jCNj', padding: CryptoJS.pad.Pkcs7
accessKeySecret: 'mveW7B1OyFoKUkHm8WsxmrjHmkJWHq', })
bucket: 'huoran' return decrypted.toString(CryptoJS.enc.Utf8)
}, }
// 上传成功url前置部分(成功回调没有返回url)
preUrl: 'https://huoran.oss-cn-shenzhen.aliyuncs.com/' const R = (encryptedKey, privateKey) => {
const decrypt = new JSEncrypt()
decrypt.setPrivateKey(privateKey)
const decryptedKey = decrypt.decrypt(encryptedKey)
return decryptedKey
}
export default async function () {
try {
const res = await get(api.encrypt)
const RE = A(R(res.encryptedKey, res.privateKey), res.encryptedData).split('/')
return {
// oss账号信息
config: {
region: 'oss-cn-shenzhen',
accessKeyId: RE[0],
accessKeySecret: RE[1],
bucket: 'huoran'
},
// 上传成功url前置部分(成功回调没有返回url)
preUrl: 'https://huoran.oss-cn-shenzhen.aliyuncs.com/'
}
} catch (e) { }
} }

@ -1,25 +1,13 @@
<template> <template>
<el-upload :disabled="uploading" <el-upload :disabled="uploading" :before-upload="beforeUpload" :on-remove="onRemove" :on-error="uploadError"
:before-upload="beforeUpload" :limit="limit" action="" :on-exceed="handleExceed" :show-file-list="showFiles" :file-list="fileList"
:on-remove="onRemove" :http-request="handleRequest" name="file">
:on-error="uploadError"
:limit="limit"
action=""
:on-exceed="handleExceed"
:show-file-list="showFiles"
:file-list="fileList"
:http-request="handleRequest"
name="file">
<slot name="trigger"> <slot name="trigger">
<el-button size="small" <el-button size="small" :loading="uploading">{{ uploading ? '正在上传' : '上传文件' }}</el-button>
:loading="uploading">{{ uploading ? '正在上传' : '上传文件' }}</el-button>
</slot> </slot>
<div slot="tip" <div slot="tip" class="el-upload__tip">
class="el-upload__tip"> <el-progress v-if="uploading" class="upload-progress" :stroke-width="3"
<el-progress v-if="uploading" :percentage="uploadProgress"></el-progress>
class="upload-progress"
:stroke-width="3"
:percentage="uploadProgress"></el-progress>
<slot name="tip"> <slot name="tip">
<p>支持扩展名.rar .zip .doc .docx .pdf .jpg...</p> <p>支持扩展名.rar .zip .doc .docx .pdf .jpg...</p>
</slot> </slot>
@ -69,7 +57,8 @@ export default {
client: null, client: null,
uploading: false, uploading: false,
uploadProgress: 0, uploadProgress: 0,
showFiles: this.showFileList showFiles: this.showFileList,
Oss: {},
}; };
}, },
mounted () { mounted () {
@ -77,8 +66,9 @@ export default {
}, },
methods: { methods: {
// oss // oss
initOss () { async initOss () {
this.client = new OSS(OssConfig.config) this.Oss = await OssConfig()
this.client = new OSS(this.Oss.config)
}, },
// //
beforeUpload (file) { beforeUpload (file) {
@ -107,7 +97,7 @@ export default {
}); });
this.uploading = false this.uploading = false
const url = OssConfig.preUrl + name const url = this.Oss.preUrl + name
this.changeFileList && this.$emit('update:fileList', [ this.changeFileList && this.$emit('update:fileList', [
...this.fileList, ...this.fileList,
{ {
@ -143,8 +133,8 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/deep/.upload-progress { /deep/.upload-progress {
max-width: 300px; max-width: 300px;
margin: 10px 0; margin: 10px 0;
white-space: nowrap; white-space: nowrap;
} }
</style> </style>

@ -5,33 +5,36 @@ import OssConfig from './config'
import Util from '@/libs/util' import Util from '@/libs/util'
let client = null let client = null
let Oss
// 初始化oss // 初始化oss
const initOss = () => { const initOss = async () => {
if (!client) client = new OSS(OssConfig.config) Oss = await OssConfig()
if (!client) client = new OSS(Oss.config)
} }
initOss()
export default { export default {
// 上传文件 // 上传文件
upload(file) { upload (file) {
initOss() initOss()
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
// 上传到阿里云oss // 上传到阿里云oss
const res = await client.multipartUpload(Date.now() + '.' + Util.getFileExt(file.name), file); const res = await client.multipartUpload(Date.now() + '.' + Util.getFileExt(file.name), file);
resolve({ resolve({
format: Util.getFileExt(file.name), format: Util.getFileExt(file.name),
name: file.name, name: file.name,
url: OssConfig.preUrl + res.name, url: Oss.preUrl + res.name,
size: file.size, size: file.size,
}) })
} catch (error) { } catch (error) {
reject() reject()
} }
}) })
}, },
// 删除文件(传完整url,不是没有https的name,因为很多接口没有存name,只存url,所以统一使用url) // 删除文件(传完整url,不是没有https的name,因为很多接口没有存name,只存url,所以统一使用url)
async del(url) { async del (url) {
initOss() initOss()
await client.delete(url.replace(OssConfig.preUrl, '')); await client.delete(url.replace(Oss.preUrl, ''));
} }
} }

@ -4,53 +4,36 @@
<div class="layout"> <div class="layout">
<navbar></navbar> <navbar></navbar>
<div class="content"> <div class="content">
<transition name="move" <transition name="move" mode="out-in">
mode="out-in">
<router-view class="view"></router-view> <router-view class="view"></router-view>
</transition> </transition>
<el-backtop target=".content"></el-backtop> <el-backtop target=".content"></el-backtop>
</div> </div>
<v-footer ref="footer"></v-footer> <v-footer ref="footer"></v-footer>
<div class="log-mask" <div class="log-mask" v-if="logVisible"></div>
v-if="logVisible"></div> <div class="log-dia" v-if="logVisible">
<div class="log-dia" <img class="bg1" src="@/assets/img/log-bg.png" alt="">
v-if="logVisible"> <img class="bg2" src="@/assets/img/log-bg1.png" alt="">
<img class="bg1"
src="@/assets/img/log-bg.png"
alt="">
<img class="bg2"
src="@/assets/img/log-bg1.png"
alt="">
<p class="log-title">更新日志</p> <p class="log-title">更新日志</p>
<div class="log-wrap"> <div class="log-wrap">
<div class="logs"> <div class="logs">
<div class="item" <div class="item" v-for="(item, i) in list" :key="i" v-show="!i || (i && logAll)">
v-for="(item, i) in list"
:key="i"
v-show="!i || (i && logAll)">
<h6>{{ item.versionName }}</h6> <h6>{{ item.versionName }}</h6>
<img v-if="item.coverUrl" <img v-if="item.coverUrl" :src="item.coverUrl" alt="" class="cover">
:src="item.coverUrl"
alt=""
class="cover">
<ul class="detail"> <ul class="detail">
<li v-for="(item, i) in item.logContents" <li v-for="(item, i) in item.logContents" :key="i">
:key="i"> <p class="name"><img
<p class="name"><img :src="require('@/assets/img/' + funcList.find(e => e.id === item.type).icon + '.png')" :src="require('@/assets/img/' + funcList.find(e => e.id === item.type).icon + '.png')" alt=""> {{
alt=""> {{ funcList.find(e => e.id === item.type).name }}</p> funcList.find(e => e.id === item.type).name }}</p>
<div class="val"> <div class="val">
<p v-for="(item, i) in item.content" <p v-for="(item, i) in item.content" :key="i">{{ i + 1 }}{{ item }}</p>
:key="i">{{ i + 1 }}{{ item }}</p>
</div> </div>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
<div class="more-wrap"> <div class="more-wrap">
<el-button class="know" <el-button class="know" type="primary" size="small" @click="logVisible = false">知道了</el-button>
type="primary"
size="small"
@click="logVisible = false">知道了</el-button>
</div> </div>
</div> </div>
</div> </div>
@ -102,7 +85,7 @@ export default {
]) ])
}, },
mounted () { mounted () {
this.autoLogout(); this.autoLogout()
this.logView || this.getLogStatus() // logViewfalse this.logView || this.getLogStatus() // logViewfalse
}, },
methods: { methods: {
@ -154,104 +137,120 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.main { .main {
min-height: 100%; min-height: 100%;
.content { .content {
min-height: calc(100vh - 176px); min-height: calc(100vh - 176px);
padding: 24px; padding: 24px;
} }
} }
.log-mask { .log-mask {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
background-color: rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.4);
} }
/deep/.log-dia { /deep/.log-dia {
z-index: 11; z-index: 11;
position: absolute;
top: 250px;
left: 50%;
width: 550px;
transform: translateX(-50%);
background-color: #fff;
border-radius: 6px;
.bg1 {
width: 100%;
height: 140px;
}
.bg2 {
position: absolute; position: absolute;
top: 250px; top: -130px;
left: 50%; left: 48px;
width: 550px; max-width: 100%;
transform: translateX(-50%); height: 250px;
background-color: #fff; }
border-radius: 6px;
.bg1 { .log-title {
width: 100%; position: absolute;
height: 140px; top: 65px;
} left: 0;
.bg2 { width: 100%;
position: absolute; text-align: center;
top: -130px; font-size: 22px;
left: 48px; color: #fff;
max-width: 100%; font-weight: 600;
height: 250px; }
}
.log-title { .log-wrap {
position: absolute; padding-bottom: 30px;
top: 65px; }
left: 0;
width: 100%; .logs {
text-align: center; max-height: 250px;
font-size: 22px; padding: 0 100px;
color: #fff; margin: 30px 0;
font-weight: 600; overflow: auto;
} }
.log-wrap {
padding-bottom: 30px; h6 {
} margin-bottom: 15px;
.logs { font-size: 16px;
max-height: 250px; color: #333;
padding: 0 100px; line-height: 1;
margin: 30px 0; }
overflow: auto;
} .more-wrap {
h6 { padding: 0 60px;
margin-bottom: 15px; font-size: 14px;
font-size: 16px; color: #333;
color: #333; text-align: center;
line-height: 1; }
}
.more-wrap { .know {
padding: 0 60px; margin-top: 15px;
font-size: 14px; }
color: #333;
text-align: center; .cover {
} max-width: 250px;
.know { max-height: 160px;
margin-top: 15px; margin: 10px 0 20px;
}
.detail {
li {
margin-bottom: 20px;
} }
.cover {
max-width: 250px; .name {
max-height: 160px; display: flex;
margin: 10px 0 20px; align-items: center;
margin-bottom: 5px;
font-size: 14px;
img {
width: 20px;
margin-right: 8px;
}
} }
.detail {
li { .val {
margin-bottom: 20px; font-size: 15px;
} line-height: 1.8;
.name { white-space: pre-wrap;
display: flex;
align-items: center; p {
margin-bottom: 5px; position: relative;
font-size: 14px; font-size: 13px;
img { color: #727272;
width: 20px; }
margin-right: 8px;
}
}
.val {
font-size: 15px;
line-height: 1.8;
white-space: pre-wrap;
p {
position: relative;
font-size: 13px;
color: #727272;
}
}
} }
}
} }
</style> </style>
Loading…
Cancel
Save