mirror of
https://github.com/Kuingsmile/PicList.git
synced 2025-01-23 06:38:13 -05:00
✨ Feature(custom): upload api now return encrypted full result
This commit is contained in:
parent
10ec712496
commit
018971509a
@ -204,6 +204,7 @@ SETTINGS_SET_SERVER_KEY: Set Auth Key
|
||||
SETTINGS_TIP_PLACEHOLDER_HOST: Default:127.0.0.1
|
||||
SETTINGS_TIP_PLACEHOLDER_PORT: Default:36677
|
||||
SETTINGS_TIP_PLACEHOLDER_KEY: This key is used to avoid malicious requests, through urlParams '?key=xxx' to pass
|
||||
SETTINGS_SET_SERVER_AES_KEY: Set AES Key for server response
|
||||
SETTINGS_LOG_LEVEL_ALL: All
|
||||
SETTINGS_LOG_LEVEL_SUCCESS: Success
|
||||
SETTINGS_LOG_LEVEL_ERROR: Error
|
||||
|
@ -206,6 +206,7 @@ SETTINGS_SET_SERVER_KEY: 设置鉴权密钥
|
||||
SETTINGS_TIP_PLACEHOLDER_HOST: 推荐默认地址:127.0.0.1
|
||||
SETTINGS_TIP_PLACEHOLDER_PORT: 推荐默认端口:36677
|
||||
SETTINGS_TIP_PLACEHOLDER_KEY: 用于接口鉴权, 通过url参数添加'?key=xxx'
|
||||
SETTINGS_SET_SERVER_AES_KEY: 设置接口数据加密密钥
|
||||
SETTINGS_LOG_LEVEL_ALL: 全部-All
|
||||
SETTINGS_LOG_LEVEL_SUCCESS: 成功-Success
|
||||
SETTINGS_LOG_LEVEL_ERROR: 错误-Error
|
||||
|
@ -204,6 +204,7 @@ SETTINGS_SET_SERVER_KEY: 設定鑒權密鑰
|
||||
SETTINGS_TIP_PLACEHOLDER_HOST: 推薦預設地址:127.0.0.1
|
||||
SETTINGS_TIP_PLACEHOLDER_PORT: 推薦預設端口:36677
|
||||
SETTINGS_TIP_PLACEHOLDER_KEY: 用於接口鑒權, 通過url參數添加'?key=xxx'
|
||||
SETTINGS_SET_SERVER_AES_KEY: 設定AES加密密鑰
|
||||
SETTINGS_LOG_LEVEL_ALL: 全部-All
|
||||
SETTINGS_LOG_LEVEL_SUCCESS: 成功-Success
|
||||
SETTINGS_LOG_LEVEL_ERROR: 錯誤-Error
|
||||
|
@ -11,6 +11,7 @@ import picgo from '@core/picgo'
|
||||
import { changeCurrentUploader } from '../utils/handleUploaderConfig'
|
||||
import { app } from 'electron'
|
||||
import fs from 'fs-extra'
|
||||
import { AESHelper } from '../utils/aesHelper'
|
||||
|
||||
const appPath = app.getPath('userData')
|
||||
const serverTempDir = path.join(appPath, 'serverTemp')
|
||||
@ -76,12 +77,18 @@ router.post('/upload', async ({
|
||||
const fullResult = result.fullResult
|
||||
logger.info('[PicList Server] upload result:', res)
|
||||
if (res) {
|
||||
const treatedFullResult = {
|
||||
isAESEncrypted: 1,
|
||||
AESEncryptedData: new AESHelper().encrypt(JSON.stringify(fullResult)),
|
||||
...fullResult
|
||||
}
|
||||
delete treatedFullResult.config
|
||||
handleResponse({
|
||||
response,
|
||||
body: {
|
||||
success: true,
|
||||
result: [res],
|
||||
fullResult: [fullResult]
|
||||
fullResult: [treatedFullResult]
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -107,7 +114,13 @@ router.post('/upload', async ({
|
||||
return item.url
|
||||
})
|
||||
const fullResult = result.map((item: any) => {
|
||||
return item.fullResult
|
||||
const treatedItem = {
|
||||
isAESEncrypted: 1,
|
||||
AESEncryptedData: new AESHelper().encrypt(JSON.stringify(item.fullResult)),
|
||||
...item.fullResult
|
||||
}
|
||||
delete treatedItem.config
|
||||
return treatedItem
|
||||
})
|
||||
logger.info('[PicList Server] upload result', res.join(' ; '))
|
||||
if (res.length) {
|
||||
@ -163,7 +176,17 @@ router.post('/delete', async ({
|
||||
return
|
||||
}
|
||||
try {
|
||||
const result = await deleteChoosedFiles(list)
|
||||
// 区分是否是aes加密的数据,如果不是直接传入list,如果是,解密后再传入
|
||||
const treatList = list.map(item => {
|
||||
if (item.isAESEncrypted) {
|
||||
const aesHelper = new AESHelper()
|
||||
const data = aesHelper.decrypt(item.AESEncryptedData)
|
||||
return JSON.parse(data)
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
})
|
||||
const result = await deleteChoosedFiles(treatList)
|
||||
const successCount = result.filter(item => item).length
|
||||
const failCount = result.filter(item => !item).length
|
||||
if (successCount) {
|
||||
|
39
src/main/utils/aesHelper.ts
Normal file
39
src/main/utils/aesHelper.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import crypto from 'crypto'
|
||||
import picgo from '@core/picgo'
|
||||
|
||||
function getDerivedKey (): Buffer {
|
||||
const userPassword = picgo.getConfig<string>('settings.aesPassword') || 'PicList-aesPassword'
|
||||
const fixedSalt = Buffer.from('a8b3c4d2e4f5098712345678feedc0de', 'hex')
|
||||
const fixedIterations = 100000
|
||||
const keyLength = 32
|
||||
return crypto.pbkdf2Sync(userPassword, fixedSalt, fixedIterations, keyLength, 'sha512')
|
||||
}
|
||||
|
||||
export class AESHelper {
|
||||
key: Buffer
|
||||
constructor () {
|
||||
this.key = getDerivedKey()
|
||||
}
|
||||
|
||||
encrypt (plainText: string) {
|
||||
const iv = crypto.randomBytes(16)
|
||||
const cipher = crypto.createCipheriv('aes-256-cbc', this.key, iv)
|
||||
let encrypted = cipher.update(plainText, 'utf8', 'hex')
|
||||
encrypted += cipher.final('hex')
|
||||
const encryptedData = `${iv.toString('hex')}:${encrypted}`
|
||||
return encryptedData
|
||||
}
|
||||
|
||||
decrypt (encryptedData: string) {
|
||||
const parts = encryptedData.split(':')
|
||||
if (parts.length !== 2) {
|
||||
return '{}'
|
||||
}
|
||||
const iv = Buffer.from(parts[0], 'hex')
|
||||
const encryptedText = parts[1]
|
||||
const decipher = crypto.createDecipheriv('aes-256-cbc', this.key, iv)
|
||||
let decrypted = decipher.update(encryptedText, 'hex', 'utf8')
|
||||
decrypted += decipher.final('utf8')
|
||||
return decrypted
|
||||
}
|
||||
}
|
@ -598,6 +598,18 @@
|
||||
{{ $T('SETTINGS_CLICK_TO_SET') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$T('SETTINGS_SET_SERVER_AES_KEY')"
|
||||
>
|
||||
<el-input
|
||||
v-model.trim="form.aesPassword"
|
||||
type="input"
|
||||
:placeholder="$T('SETTINGS_SET_SERVER_AES_KEY')"
|
||||
size="small"
|
||||
style="width: 50%"
|
||||
@change="handleAesPasswordChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
</el-col>
|
||||
@ -1702,7 +1714,8 @@ const form = reactive<ISettingForm>({
|
||||
yourlsDomain: '',
|
||||
yourlsSignature: '',
|
||||
deleteLocalFile: false,
|
||||
serverKey: ''
|
||||
serverKey: '',
|
||||
aesPassword: ''
|
||||
})
|
||||
|
||||
const languageList = i18nManager.languageList.map(item => ({
|
||||
@ -1860,6 +1873,7 @@ async function initData () {
|
||||
form.yourlsSignature = settings.yourlsSignature || ''
|
||||
form.deleteLocalFile = settings.deleteLocalFile || false
|
||||
form.serverKey = settings.serverKey || ''
|
||||
form.aesPassword = settings.aesPassword || 'PicList-aesPassword'
|
||||
currentLanguage.value = settings.language ?? 'zh-CN'
|
||||
currentStartMode.value = settings.startMode || 'quiet'
|
||||
customLink.value = settings.customLink || '![$fileName]($url)'
|
||||
@ -2210,6 +2224,10 @@ function handleYourlsSignatureChange (val: string) {
|
||||
saveConfig('settings.yourlsSignature', val)
|
||||
}
|
||||
|
||||
function handleAesPasswordChange (val: string) {
|
||||
saveConfig('settings.aesPassword', val || 'PicList-aesPassword')
|
||||
}
|
||||
|
||||
function confirmLogLevelSetting () {
|
||||
if (form.logLevel.length === 0) {
|
||||
return $message.error($T('TIPS_PLEASE_CHOOSE_LOG_LEVEL'))
|
||||
|
1
src/universal/types/i18n.d.ts
vendored
1
src/universal/types/i18n.d.ts
vendored
@ -199,6 +199,7 @@ interface ILocales {
|
||||
SETTINGS_TIP_PLACEHOLDER_HOST: string
|
||||
SETTINGS_TIP_PLACEHOLDER_PORT: string
|
||||
SETTINGS_TIP_PLACEHOLDER_KEY: string
|
||||
SETTINGS_SET_SERVER_AES_KEY: string
|
||||
SETTINGS_LOG_LEVEL_ALL: string
|
||||
SETTINGS_LOG_LEVEL_SUCCESS: string
|
||||
SETTINGS_LOG_LEVEL_ERROR: string
|
||||
|
3
src/universal/types/view.d.ts
vendored
3
src/universal/types/view.d.ts
vendored
@ -28,7 +28,8 @@ interface ISettingForm {
|
||||
yourlsDomain: string,
|
||||
yourlsSignature: string,
|
||||
deleteLocalFile: boolean,
|
||||
serverKey: string
|
||||
serverKey: string,
|
||||
aesPassword: string
|
||||
}
|
||||
|
||||
interface IShortKeyMap {
|
||||
|
Loading…
Reference in New Issue
Block a user