From cac8820983ae86bc0e98b642205c1cf17cb56d87 Mon Sep 17 00:00:00 2001 From: yuzl6 Date: Mon, 8 Apr 2024 22:28:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8A=A8=E6=80=81=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8A=A0=E5=AF=86=EF=BC=8C=E5=A2=9E=E5=8A=A0dockerfil?= =?UTF-8?q?e=E9=83=A8=E7=BD=B2=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.development | 1 + .env.production | 1 + Dockerfile | 9 ++++++ default.conf | 29 +++++++++++++++++ package.json | 1 + src/api/genKeyPair.ts | 18 +++++++++++ src/api/login.ts | 58 ++++++++++++++++++++++++---------- src/api/system/tenant/index.ts | 28 ++++++++++++---- src/api/system/user/index.ts | 54 +++++++++++++++++++++++-------- src/types/env.d.ts | 3 +- src/utils/jsencrypt.ts | 8 ++--- src/utils/request.ts | 13 +++++--- 12 files changed, 176 insertions(+), 47 deletions(-) create mode 100644 Dockerfile create mode 100644 default.conf create mode 100644 src/api/genKeyPair.ts diff --git a/.env.development b/.env.development index 772fc85..27628ae 100644 --- a/.env.development +++ b/.env.development @@ -21,6 +21,7 @@ VITE_APP_EASYRETRY_ADMIN = 'http://localhost:8800/easy-retry' VITE_APP_PORT = 80 +VITE_APP_ENCRYPT_HEADER = 'encrypt-key' # 接口加密功能开关(如需关闭 后端也必须对应关闭) VITE_APP_ENCRYPT = true # 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换 diff --git a/.env.production b/.env.production index 1f54216..8f0d5c3 100644 --- a/.env.production +++ b/.env.production @@ -24,6 +24,7 @@ VITE_BUILD_COMPRESS = gzip VITE_APP_PORT = 80 +VITE_APP_ENCRYPT_HEADER = 'encrypt-key' # 接口加密功能开关(如需关闭 后端也必须对应关闭) VITE_APP_ENCRYPT = true # 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..22a84ad --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM nginx + +MAINTAINER onesummer + +RUN rm /etc/nginx/conf.d/default.conf + +ADD default.conf /etc/nginx/conf.d/ + +COPY dist/ /usr/share/nginx/html/ diff --git a/default.conf b/default.conf new file mode 100644 index 0000000..dfa5f13 --- /dev/null +++ b/default.conf @@ -0,0 +1,29 @@ +server { + listen 80; + server_name localhost; + charset utf-8; + + location / { + root /usr/share/nginx/html; + try_files $uri $uri/ /index.html; + index index.html index.htm; + } + + location /prod-api/ { + proxy_pass http://172.16.0.151:8080/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $http_host; + proxy_set_header X-Forwarded-Port $server_port; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } +} diff --git a/package.json b/package.json index 7532916..217de1b 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "crypto-js": "4.2.0", "echarts": "5.5.0", "element-plus": "2.6.2", + "encryptlong": "^3.1.4", "file-saver": "2.0.5", "fuse.js": "7.0.0", "image-conversion": "^2.1.1", diff --git a/src/api/genKeyPair.ts b/src/api/genKeyPair.ts new file mode 100644 index 0000000..1e0d282 --- /dev/null +++ b/src/api/genKeyPair.ts @@ -0,0 +1,18 @@ +import request from '@/utils/request'; + +/** + * 生成密钥对 + * @param callback + */ +export function genKeyPair(callback: Function) { + return request({ + url: '/genKeyPair', + headers: { + isToken: false, + repeatSubmit: false + }, + method: 'get' + }).then((res) => { + return callback(res.data.uuidPrivateKey, res.data.RSA_PUBLIC_KEY); + }); +} diff --git a/src/api/login.ts b/src/api/login.ts index 100a5e9..c39f72a 100644 --- a/src/api/login.ts +++ b/src/api/login.ts @@ -2,9 +2,11 @@ import request from '@/utils/request'; import { AxiosPromise } from 'axios'; import { LoginData, LoginResult, VerifyCodeResult, TenantInfo } from './types'; import { UserInfo } from '@/api/system/user/types'; +import { genKeyPair } from '@/api/genKeyPair'; // pc端固定客户端授权id const clientId = import.meta.env.VITE_APP_CLIENT_ID; +const encryptHeader = import.meta.env.VITE_APP_ENCRYPT_HEADER; /** * @param data {LoginData} @@ -16,14 +18,26 @@ export function login(data: LoginData): AxiosPromise { clientId: data.clientId || clientId, grantType: data.grantType || 'password' }; - return request({ - url: '/auth/login', - headers: { - isToken: false, - isEncrypt: true - }, - method: 'post', - data: params + return new Promise((resolve, reject) => { + genKeyPair((uuid, public_key) => { + request({ + url: '/auth/login', + headers: { + isToken: false, + isEncrypt: true, + [encryptHeader]: uuid, + publicKey: public_key + }, + method: 'post', + data: params + }) + .then((res) => { + resolve(res); + }) + .catch((error) => { + reject(error); + }); + }); }); } @@ -34,14 +48,26 @@ export function register(data: any) { clientId: clientId, grantType: 'password' }; - return request({ - url: '/auth/register', - headers: { - isToken: false, - isEncrypt: true - }, - method: 'post', - data: params + return new Promise((resolve, reject) => { + genKeyPair((uuid, public_key) => { + request({ + url: '/auth/register', + headers: { + isToken: false, + isEncrypt: true, + [encryptHeader]: uuid, + publicKey: public_key + }, + method: 'post', + data: params + }) + .then((res) => { + resolve(res); + }) + .catch((error) => { + reject(error); + }); + }); }); } diff --git a/src/api/system/tenant/index.ts b/src/api/system/tenant/index.ts index 8118d82..ec38817 100644 --- a/src/api/system/tenant/index.ts +++ b/src/api/system/tenant/index.ts @@ -1,6 +1,8 @@ import request from '@/utils/request'; import { TenantForm, TenantQuery, TenantVO } from './types'; import { AxiosPromise } from 'axios'; +import { genKeyPair } from '@/api/genKeyPair'; +const encryptHeader = import.meta.env.VITE_APP_ENCRYPT_HEADER; // 查询租户列表 export function listTenant(query: TenantQuery): AxiosPromise { @@ -21,13 +23,25 @@ export function getTenant(tenantId: string | number): AxiosPromise { // 新增租户 export function addTenant(data: TenantForm) { - return request({ - url: '/system/tenant', - method: 'post', - headers: { - isEncrypt: true - }, - data: data + return new Promise((resolve, reject) => { + genKeyPair((uuid, public_key) => { + request({ + url: '/system/tenant', + method: 'post', + headers: { + isEncrypt: true, + [encryptHeader]: uuid, + publicKey: public_key + }, + data: data + }) + .then((res) => { + resolve(res); + }) + .catch((error) => { + reject(error); + }); + }); }); } diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts index 6303b46..77a9050 100644 --- a/src/api/system/user/index.ts +++ b/src/api/system/user/index.ts @@ -4,6 +4,8 @@ import request from '@/utils/request'; import { AxiosPromise } from 'axios'; import { UserForm, UserQuery, UserVO, UserInfoVO } from './types'; import { parseStrEmpty } from '@/utils/ruoyi'; +import { genKeyPair } from '@/api/genKeyPair'; +const encryptHeader = import.meta.env.VITE_APP_ENCRYPT_HEADER; /** * 查询用户列表 @@ -72,13 +74,25 @@ export const resetUserPwd = (userId: string | number, version: number, password: version, password }; - return request({ - url: '/system/user/resetPwd', - method: 'put', - headers: { - isEncrypt: true - }, - data: data + return new Promise((resolve, reject) => { + genKeyPair((uuid, public_key) => { + request({ + url: '/system/user/resetPwd', + method: 'put', + headers: { + isEncrypt: true, + [encryptHeader]: uuid, + publicKey: public_key + }, + data: data + }) + .then((res) => { + resolve(res); + }) + .catch((error) => { + reject(error); + }); + }); }); }; @@ -132,13 +146,25 @@ export const updateUserPwd = (oldPassword: string, newPassword: string) => { oldPassword, newPassword }; - return request({ - url: '/system/user/profile/updatePwd', - method: 'put', - headers: { - isEncrypt: true - }, - data: data + return new Promise((resolve, reject) => { + genKeyPair((uuid, public_key) => { + request({ + url: '/system/user/profile/updatePwd', + method: 'put', + headers: { + isEncrypt: true, + [encryptHeader]: uuid, + publicKey: public_key + }, + data: data + }) + .then((res) => { + resolve(res); + }) + .catch((error) => { + reject(error); + }); + }); }); }; diff --git a/src/types/env.d.ts b/src/types/env.d.ts index 5b18a8e..d64e8a0 100644 --- a/src/types/env.d.ts +++ b/src/types/env.d.ts @@ -14,10 +14,11 @@ interface ImportMetaEnv { VITE_APP_MONITRO_ADMIN: string; VITE_APP_POWERJOB_ADMIN: string; VITE_APP_ENV: string; - VITE_APP_ENCRYPT: string + VITE_APP_ENCRYPT: string; VITE_APP_RSA_PUBLIC_KEY: string; VITE_APP_RSA_PRIVATE_KEY: string; VITE_APP_CLIENT_ID: string; + VITE_APP_ENCRYPT_HEADER: string; VITE_APP_WEBSOCKET: string; } interface ImportMeta { diff --git a/src/utils/jsencrypt.ts b/src/utils/jsencrypt.ts index 42de5a0..f42e469 100644 --- a/src/utils/jsencrypt.ts +++ b/src/utils/jsencrypt.ts @@ -1,16 +1,14 @@ -import JSEncrypt from 'jsencrypt'; +import JSEncrypt from 'encryptlong'; // 密钥对生成 http://web.chacuo.net/netrsakeypair -const publicKey = import.meta.env.VITE_APP_RSA_PUBLIC_KEY; - // 前端不建议存放私钥 不建议解密数据 因为都是透明的意义不大 const privateKey = import.meta.env.VITE_APP_RSA_PRIVATE_KEY; // 加密 -export const encrypt = (txt: string) => { +export const encrypt = (txt: string, publicKey: string) => { const encryptor = new JSEncrypt(); encryptor.setPublicKey(publicKey); // 设置公钥 - return encryptor.encrypt(txt); // 对数据进行加密 + return encryptor.encryptLong(txt); // 对数据进行加密 }; // 解密 diff --git a/src/utils/request.ts b/src/utils/request.ts index f2a69f0..88e6be7 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -10,6 +10,7 @@ import FileSaver from 'file-saver'; import { getLanguage } from '@/lang'; import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto'; import { encrypt, decrypt } from '@/utils/jsencrypt'; +import { ElLoading, ElMessage, ElMessageBox, ElNotification } from 'element-plus'; const encryptHeader = 'encrypt-key'; let downloadLoadingInstance: LoadingInstance; @@ -79,10 +80,14 @@ service.interceptors.request.use( if (import.meta.env.VITE_APP_ENCRYPT === 'true') { // 当开启参数加密 if (isEncrypt && (config.method === 'post' || config.method === 'put')) { - // 生成一个 AES 密钥 - const aesKey = generateAesKey(); - config.headers[encryptHeader] = encrypt(encryptBase64(aesKey)); - config.data = typeof config.data === 'object' ? encryptWithAes(JSON.stringify(config.data), aesKey) : encryptWithAes(config.data, aesKey); + // 根据 AES 密钥进行加密 + const publicKey = (config.headers || {}).publicKey; + console.log('publicKey', publicKey); + config.data = + typeof config.data === 'object' + ? encrypt(encodeURIComponent(JSON.stringify(config.data)), publicKey) + : encrypt(encodeURIComponent(config.data), publicKey); + delete config.headers['publicKey']; } } // FormData数据去请求头Content-Type