From 43edef412cc36059e5eb2371bd6159e20ce2e572 Mon Sep 17 00:00:00 2001 From: zongyangleo Date: Thu, 22 Aug 2024 00:43:39 +0000 Subject: [PATCH] =?UTF-8?q?!123=20=E4=B8=80=E4=BA=9Bbug=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20*=20fix:=20=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5=E3=80=81?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=BF=81=E7=A7=BB=E4=BD=93=E9=AA=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20*=20fix:=20des=E5=8A=A0=E5=AF=86=E4=BC=A0=E8=BE=93s?= =?UTF-8?q?ql=20*=20fix:=20=E4=BF=AE=E5=A4=8D=E8=BE=BE=E6=A2=A6=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E6=B3=A8=E9=87=8A=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20*=20fix:=20mysql=20timestamp=20=E5=AD=97=E6=AE=B5=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=AF=BC=E5=87=BAddl=E9=94=99=E8=AF=AF=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mayfly_go_web/.env | 4 +- mayfly_go_web/package.json | 2 + mayfly_go_web/src/common/Api.ts | 2 +- mayfly_go_web/src/common/des.ts | 48 ++++++++++++++ mayfly_go_web/src/common/utils/viteBuild.ts | 1 + mayfly_go_web/src/hooks/useRequest.ts | 4 +- .../src/views/ops/db/DbTransferEdit.vue | 4 ++ .../src/views/ops/db/DbTransferList.vue | 14 ++-- .../src/views/ops/db/SyncTaskEdit.vue | 4 +- mayfly_go_web/src/views/ops/db/api.ts | 39 +++++------ mayfly_go_web/vite.config.ts | 3 +- server/internal/db/api/db.go | 9 +-- server/internal/db/api/db_data_sync.go | 6 +- server/internal/db/api/form/db_transfer.go | 1 + server/internal/db/api/vo/db_transfer.go | 1 + .../internal/db/dbm/dbi/metasql/dm_meta.sql | 10 +-- server/internal/db/dbm/mysql/metadata.go | 14 +++- .../internal/db/domain/entity/db_transfer.go | 1 + server/internal/db/domain/entity/query.go | 1 + .../infrastructure/persistence/db_transfer.go | 4 +- server/pkg/model/login_account.go | 1 + server/pkg/req/permission_handler.go | 1 + server/pkg/utils/cryptox/cryptox.go | 64 +++++++++++++++++++ server/pkg/utils/cryptox/cryptox_test.go | 35 ++++++++++ server/resources/script/sql/mayfly-go.sql | 1 + server/resources/script/sql/v1.8/v1.8.9.sql | 2 + 26 files changed, 226 insertions(+), 50 deletions(-) create mode 100644 mayfly_go_web/src/common/des.ts create mode 100644 server/pkg/utils/cryptox/cryptox_test.go create mode 100644 server/resources/script/sql/v1.8/v1.8.9.sql diff --git a/mayfly_go_web/.env b/mayfly_go_web/.env index 17542d05..6b00532c 100644 --- a/mayfly_go_web/.env +++ b/mayfly_go_web/.env @@ -5,4 +5,6 @@ VITE_PORT = 8889 VITE_OPEN = false # public path 配置线上环境路径(打包) -VITE_PUBLIC_PATH = '' \ No newline at end of file +VITE_PUBLIC_PATH = '' + +VITE_EDITOR=idea \ No newline at end of file diff --git a/mayfly_go_web/package.json b/mayfly_go_web/package.json index a7293ac3..733f508f 100644 --- a/mayfly_go_web/package.json +++ b/mayfly_go_web/package.json @@ -42,6 +42,7 @@ "xterm-addon-web-links": "^0.9.0" }, "devDependencies": { + "@types/crypto-js": "^4.2.2", "@types/lodash": "^4.14.178", "@types/node": "^18.14.0", "@types/nprogress": "^0.2.0", @@ -51,6 +52,7 @@ "@vitejs/plugin-vue": "^5.0.5", "@vue/compiler-sfc": "^3.4.32", "code-inspector-plugin": "^0.4.5", + "crypto-js": "^4.2.0", "dotenv": "^16.3.1", "eslint": "^8.35.0", "eslint-plugin-vue": "^9.25.0", diff --git a/mayfly_go_web/src/common/Api.ts b/mayfly_go_web/src/common/Api.ts index bc8a5323..3a4c6b78 100644 --- a/mayfly_go_web/src/common/Api.ts +++ b/mayfly_go_web/src/common/Api.ts @@ -69,7 +69,7 @@ class Api { */ async xhrReq(param: any = null, options: any = {}): Promise { if (this.beforeHandler) { - this.beforeHandler(param); + await this.beforeHandler(param); } return request.xhrReq(this.method, this.url, param, options); } diff --git a/mayfly_go_web/src/common/des.ts b/mayfly_go_web/src/common/des.ts new file mode 100644 index 00000000..5d4e3251 --- /dev/null +++ b/mayfly_go_web/src/common/des.ts @@ -0,0 +1,48 @@ +import CryptoJS from 'crypto-js'; +import { getToken } from '@/common/utils/storage'; + +/** + * AES 加密数据 + * @param word + * @param key + */ +export function DesEncrypt(word: string, key?: string) { + if (!key) { + key = getToken().substring(0, 24); + } + const srcs = CryptoJS.enc.Utf8.parse(word); + const iv = CryptoJS.lib.WordArray.random(8); // 生成随机IV + const encrypted = CryptoJS.TripleDES.encrypt(srcs, CryptoJS.enc.Utf8.parse(key), { + iv: iv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }); + + return iv.concat(encrypted.ciphertext).toString(CryptoJS.enc.Base64); +} + +/** + * AES 解密 :字符串 key iv 返回base64 + * */ +export function DesDecrypt(encryptedData: string, key?: string) { + if (!key) { + key = getToken().substring(0, 32); + } + // 解码Base64 + const ciphertext = CryptoJS.enc.Base64.parse(encryptedData); + + // 分离IV和加密数据 + const iv = ciphertext.clone(); + iv.sigBytes = 8; + iv.clamp(); + ciphertext.words.splice(0, 2); // 移除IV + ciphertext.sigBytes -= 8; + + const decrypted = CryptoJS.TripleDES.decrypt({ ciphertext } as any, CryptoJS.enc.Utf8.parse(key), { + iv: iv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }); + + return decrypted.toString(CryptoJS.enc.Utf8); +} diff --git a/mayfly_go_web/src/common/utils/viteBuild.ts b/mayfly_go_web/src/common/utils/viteBuild.ts index 032b6e75..3209d952 100644 --- a/mayfly_go_web/src/common/utils/viteBuild.ts +++ b/mayfly_go_web/src/common/utils/viteBuild.ts @@ -4,6 +4,7 @@ export interface ViteEnv { VITE_PORT: number; VITE_OPEN: boolean; VITE_PUBLIC_PATH: string; + VITE_EDITOR: string; } export function loadEnv(): ViteEnv { diff --git a/mayfly_go_web/src/hooks/useRequest.ts b/mayfly_go_web/src/hooks/useRequest.ts index 46a9263c..916fe42b 100644 --- a/mayfly_go_web/src/hooks/useRequest.ts +++ b/mayfly_go_web/src/hooks/useRequest.ts @@ -42,7 +42,7 @@ const useCustomFetch = createFetch({ export function useApiFetch(api: Api, params: any = null, reqOptions: RequestInit = {}) { const uaf = useCustomFetch(api.url, { - beforeFetch({ url, options }) { + async beforeFetch({ url, options }) { options.method = api.method; if (!params) { return; @@ -57,7 +57,7 @@ export function useApiFetch(api: Api, params: any = null, reqOptions: Request } if (api.beforeHandler) { - paramsValue = api.beforeHandler(paramsValue); + paramsValue = await api.beforeHandler(paramsValue); } if (paramsValue) { diff --git a/mayfly_go_web/src/views/ops/db/DbTransferEdit.vue b/mayfly_go_web/src/views/ops/db/DbTransferEdit.vue index cc87ed13..7164ef80 100644 --- a/mayfly_go_web/src/views/ops/db/DbTransferEdit.vue +++ b/mayfly_go_web/src/views/ops/db/DbTransferEdit.vue @@ -12,6 +12,9 @@ + + + 删除 + @@ -26,7 +31,7 @@ - {{ data.targetInstName }} + {{ data.targetDbName }} @@ -71,8 +76,9 @@ const perms = { const searchItems = [SearchItem.input('name', '名称')]; const columns = ref([ - TableColumn.new('srcDb', '源库').setMinWidth(200).isSlot(), - TableColumn.new('targetDb', '目标库').setMinWidth(200).isSlot(), + TableColumn.new('taskName', '任务名').setMinWidth(150).isSlot(), + TableColumn.new('srcDb', '源库').setMinWidth(150).isSlot(), + TableColumn.new('targetDb', '目标库').setMinWidth(150).isSlot(), TableColumn.new('runningState', '执行状态').typeTag(DbTransferRunningStateEnum), TableColumn.new('creator', '创建人'), TableColumn.new('createTime', '创建时间').isTime(), diff --git a/mayfly_go_web/src/views/ops/db/SyncTaskEdit.vue b/mayfly_go_web/src/views/ops/db/SyncTaskEdit.vue index 950428cb..220339a8 100644 --- a/mayfly_go_web/src/views/ops/db/SyncTaskEdit.vue +++ b/mayfly_go_web/src/views/ops/db/SyncTaskEdit.vue @@ -328,7 +328,7 @@ watch(dialogVisible, async (newValue: boolean) => { db.databases = db.database?.split(' ').sort() || []; state.srcDbInst = DbInst.getOrNewInst(db); state.form.srcDbType = state.srcDbInst.type; - state.form.srcInstName = db.instanceName; + state.form.srcInstName = db.name; } // 初始化target数据源 @@ -340,7 +340,7 @@ watch(dialogVisible, async (newValue: boolean) => { db.databases = db.database?.split(' ').sort() || []; state.targetDbInst = DbInst.getOrNewInst(db); state.form.targetDbType = state.targetDbInst.type; - state.form.targetInstName = db.instanceName; + state.form.targetInstName = db.name; } if (targetDbId && state.form.targetDbName) { diff --git a/mayfly_go_web/src/views/ops/db/api.ts b/mayfly_go_web/src/views/ops/db/api.ts index 0b98c4a1..4640ca04 100644 --- a/mayfly_go_web/src/views/ops/db/api.ts +++ b/mayfly_go_web/src/views/ops/db/api.ts @@ -1,5 +1,5 @@ import Api from '@/common/Api'; -import { Base64 } from 'js-base64'; +import { DesEncrypt } from '@/common/des'; export const dbApi = { // 获取权限列表 @@ -16,20 +16,7 @@ export const dbApi = { pgSchemas: Api.newGet('/dbs/{id}/pg/schemas'), // 获取表即列提示 hintTables: Api.newGet('/dbs/{id}/hint-tables'), - sqlExec: Api.newPost('/dbs/{id}/exec-sql').withBeforeHandler((param: any) => { - // sql编码处理 - if (param.sql) { - // 判断是开发环境就打印sql - if (process.env.NODE_ENV === 'development') { - console.log(param.sql); - } - // 非base64编码sql,则进行base64编码(refreshToken时,会重复调用该方法,故简单判断下) - if (!Base64.isValid(param.sql)) { - param.sql = Base64.encode(param.sql); - } - } - return param; - }), + sqlExec: Api.newPost('/dbs/{id}/exec-sql').withBeforeHandler(async (param: any) => await encryptField(param, 'sql')), // 保存sql saveSql: Api.newPost('/dbs/{id}/sql'), // 获取保存的sql @@ -73,13 +60,7 @@ export const dbApi = { // 数据同步相关 datasyncTasks: Api.newGet('/datasync/tasks'), - saveDatasyncTask: Api.newPost('/datasync/tasks/save').withBeforeHandler((param: any) => { - // sql编码处理 - if (param.dataSql) { - param.dataSql = Base64.encode(param.dataSql); - } - return param; - }), + saveDatasyncTask: Api.newPost('/datasync/tasks/save').withBeforeHandler(async (param: any) => await encryptField(param, 'dataSql')), getDatasyncTask: Api.newGet('/datasync/tasks/{taskId}'), deleteDatasyncTask: Api.newDelete('/datasync/tasks/{taskId}/del'), updateDatasyncTaskStatus: Api.newPost('/datasync/tasks/{taskId}/status'), @@ -100,3 +81,17 @@ export const dbSqlExecApi = { // 根据业务key获取sql执行信息 getSqlExecByBizKey: Api.newGet('/dbs/sql-execs'), }; +const encryptField = async (param: any, field: string) => { + // sql编码处理 + if (!param['_encrypted'] && param[field]) { + // 判断是开发环境就打印sql + if (process.env.NODE_ENV === 'development') { + console.log(param[field]); + } + // 使用rsa公钥加密sql + param['_encrypted'] = 1; + param[field] = DesEncrypt(param[field]); + // console.log('解密结果', DesDecrypt(param[field])); + } + return param; +}; diff --git a/mayfly_go_web/vite.config.ts b/mayfly_go_web/vite.config.ts index 17a20c10..25b48e0a 100644 --- a/mayfly_go_web/vite.config.ts +++ b/mayfly_go_web/vite.config.ts @@ -8,7 +8,7 @@ const pathResolve = (dir: string): any => { return resolve(__dirname, '.', dir); }; -const { VITE_PORT, VITE_OPEN, VITE_PUBLIC_PATH } = loadEnv(); +const { VITE_PORT, VITE_OPEN, VITE_PUBLIC_PATH, VITE_EDITOR } = loadEnv(); const alias: Record = { '@': pathResolve('src/'), @@ -19,6 +19,7 @@ const viteConfig: UserConfig = { vue(), CodeInspectorPlugin({ bundler: 'vite', + editor: VITE_EDITOR, }), ], root: process.cwd(), diff --git a/server/internal/db/api/db.go b/server/internal/db/api/db.go index 50fff762..6efb85fa 100644 --- a/server/internal/db/api/db.go +++ b/server/internal/db/api/db.go @@ -2,7 +2,6 @@ package api import ( "context" - "encoding/base64" "fmt" "io" "mayfly-go/internal/db/api/form" @@ -24,6 +23,7 @@ import ( "mayfly-go/pkg/req" "mayfly-go/pkg/utils/anyx" "mayfly-go/pkg/utils/collx" + "mayfly-go/pkg/utils/cryptox" "mayfly-go/pkg/utils/stringx" "mayfly-go/pkg/ws" "strings" @@ -103,17 +103,18 @@ func (d *Db) DeleteDb(rc *req.Ctx) { func (d *Db) ExecSql(rc *req.Ctx) { form := req.BindJsonAndValid(rc, new(form.DbSqlExecForm)) + ui := rc.GetLoginAccount() + dbId := getDbId(rc) dbConn, err := d.DbApp.GetDbConn(dbId, form.Db) biz.ErrIsNil(err) biz.ErrIsNilAppendErr(d.TagApp.CanAccess(rc.GetLoginAccount().Id, dbConn.Info.CodePath...), "%s") global.EventBus.Publish(rc.MetaCtx, event.EventTopicResourceOp, dbConn.Info.CodePath[0]) - - sqlBytes, err := base64.StdEncoding.DecodeString(form.Sql) + sqlStr, err := cryptox.DesDecryptByToken(form.Sql, ui.Token) biz.ErrIsNilAppendErr(err, "sql解码失败: %s") // 去除前后空格及换行符 - sql := stringx.TrimSpaceAndBr(string(sqlBytes)) + sql := stringx.TrimSpaceAndBr(sqlStr) rc.ReqParam = fmt.Sprintf("%s %s\n-> %s", dbConn.Info.GetLogDesc(), form.ExecId, sql) biz.NotEmpty(form.Sql, "sql不能为空") diff --git a/server/internal/db/api/db_data_sync.go b/server/internal/db/api/db_data_sync.go index e6375599..6f85d8f5 100644 --- a/server/internal/db/api/db_data_sync.go +++ b/server/internal/db/api/db_data_sync.go @@ -1,13 +1,13 @@ package api import ( - "encoding/base64" "mayfly-go/internal/db/api/form" "mayfly-go/internal/db/api/vo" "mayfly-go/internal/db/application" "mayfly-go/internal/db/domain/entity" "mayfly-go/pkg/biz" "mayfly-go/pkg/req" + "mayfly-go/pkg/utils/cryptox" "mayfly-go/pkg/utils/stringx" "strconv" "strings" @@ -36,9 +36,9 @@ func (d *DataSyncTask) SaveTask(rc *req.Ctx) { task := req.BindJsonAndCopyTo[*entity.DataSyncTask](rc, form, new(entity.DataSyncTask)) // 解码base64 sql - sqlBytes, err := base64.StdEncoding.DecodeString(task.DataSql) + sqlStr, err := cryptox.DesDecryptByToken(task.DataSql, rc.GetLoginAccount().Token) biz.ErrIsNilAppendErr(err, "sql解码失败: %s") - sql := stringx.TrimSpaceAndBr(string(sqlBytes)) + sql := stringx.TrimSpaceAndBr(sqlStr) task.DataSql = sql form.DataSql = sql diff --git a/server/internal/db/api/form/db_transfer.go b/server/internal/db/api/form/db_transfer.go index 1b559846..b69087e9 100644 --- a/server/internal/db/api/form/db_transfer.go +++ b/server/internal/db/api/form/db_transfer.go @@ -2,6 +2,7 @@ package form type DbTransferTaskForm struct { Id uint64 `json:"id"` + TaskName string `binding:"required" json:"taskName"` // 任务名称 CheckedKeys string `binding:"required" json:"checkedKeys"` // 选中需要迁移的表 DeleteTable int `binding:"required" json:"deleteTable"` // 创建表前是否删除表 1是 2否 NameCase int `binding:"required" json:"nameCase"` // 表名、字段大小写转换 1无 2大写 3小写 diff --git a/server/internal/db/api/vo/db_transfer.go b/server/internal/db/api/vo/db_transfer.go index 5dab98dc..abc607da 100644 --- a/server/internal/db/api/vo/db_transfer.go +++ b/server/internal/db/api/vo/db_transfer.go @@ -11,6 +11,7 @@ type DbTransferTaskListVO struct { RunningState int `json:"runningState"` LogId uint64 `json:"logId"` + TaskName string `json:"taskName"` // 任务名称 CheckedKeys string `json:"checkedKeys"` // 选中需要迁移的表 DeleteTable int `json:"deleteTable"` // 创建表前是否删除表 diff --git a/server/internal/db/dbm/dbi/metasql/dm_meta.sql b/server/internal/db/dbm/dbi/metasql/dm_meta.sql index 1c8c2c1b..924cb5d8 100644 --- a/server/internal/db/dbm/dbi/metasql/dm_meta.sql +++ b/server/internal/db/dbm/dbi/metasql/dm_meta.sql @@ -60,15 +60,15 @@ select a.owner, a.char_col_decl_length as CHAR_MAX_LENGTH, a.data_precision as NUM_PRECISION, a.data_scale as NUM_SCALE, - b.comments as COLUMN_COMMENT, + b.COMMENT$ as COLUMN_COMMENT, a.data_default as COLUMN_DEFAULT, case when t.INFO2 & 0x01 = 0x01 then 1 else 0 end as IS_IDENTITY, case when t2.constraint_type = 'P' then 1 else 0 end as IS_PRIMARY_KEY from all_tab_columns a - left join all_col_comments b - on b.owner = (SELECT SF_GET_SCHEMA_NAME_BY_ID(CURRENT_SCHID)) - and b.table_name = a.table_name - and a.column_name = b.column_name + left join SYSCOLUMNCOMMENTS b + on b.SCHNAME = (SELECT SF_GET_SCHEMA_NAME_BY_ID(CURRENT_SCHID)) + and b.TVNAME = a.table_name + and a.column_name = b.COLNAME left join (select c1.*, c2.object_name, c2.owner FROM SYS.SYSCOLUMNS c1 join SYS.all_objects c2 on c1.id = c2.object_id and c2.object_type = 'TABLE') t diff --git a/server/internal/db/dbm/mysql/metadata.go b/server/internal/db/dbm/mysql/metadata.go index cc5d8da5..58bab987 100644 --- a/server/internal/db/dbm/mysql/metadata.go +++ b/server/internal/db/dbm/mysql/metadata.go @@ -217,9 +217,17 @@ func (md *MysqlMetaData) genColumnBasicSql(column dbi.Column) string { if !column.Nullable { nullAble = " NOT NULL" } + columnType := column.GetColumnType() + if nullAble == "" && strings.Contains(columnType, "timestamp") { + nullAble = " NULL" + } - defVal := "" // 默认值需要判断引号,如函数是不需要引号的 // 为了防止跨源函数不支持 当默认值是函数时,不需要设置默认值 - if column.ColumnDefault != "" && !strings.Contains(column.ColumnDefault, "(") { + defVal := "" // 默认值需要判断引号,如函数是不需要引号的 + if column.ColumnDefault != "" && + // 当默认值是字符串'NULL'时,不需要设置默认值 + column.ColumnDefault != "NULL" && + // 为了防止跨源函数不支持 当默认值是函数时,不需要设置默认值 + !strings.Contains(column.ColumnDefault, "(") { // 哪些字段类型默认值需要加引号 mark := false if collx.ArrayAnyMatches([]string{"char", "text", "date", "time", "lob"}, strings.ToLower(dataType)) { @@ -244,7 +252,7 @@ func (md *MysqlMetaData) genColumnBasicSql(column dbi.Column) string { comment = fmt.Sprintf(" COMMENT '%s'", commentStr) } - columnSql := fmt.Sprintf(" %s %s%s%s%s%s", md.dc.GetMetaData().QuoteIdentifier(column.ColumnName), column.GetColumnType(), nullAble, incr, defVal, comment) + columnSql := fmt.Sprintf(" %s %s%s%s%s%s", md.dc.GetMetaData().QuoteIdentifier(column.ColumnName), columnType, nullAble, incr, defVal, comment) return columnSql } diff --git a/server/internal/db/domain/entity/db_transfer.go b/server/internal/db/domain/entity/db_transfer.go index 3bb015b0..d7c8097a 100644 --- a/server/internal/db/domain/entity/db_transfer.go +++ b/server/internal/db/domain/entity/db_transfer.go @@ -9,6 +9,7 @@ type DbTransferTask struct { RunningState DbTransferRunningState `orm:"column(running_state)" json:"runningState"` // 运行状态 LogId uint64 `json:"logId"` + TaskName string `orm:"column(task_name)" json:"taskName"` // 任务名称 CheckedKeys string `orm:"column(checked_keys)" json:"checkedKeys"` // 选中需要迁移的表 DeleteTable int `orm:"column(delete_table)" json:"deleteTable"` // 创建表前是否删除表 diff --git a/server/internal/db/domain/entity/query.go b/server/internal/db/domain/entity/query.go index 8d11d579..614dc48a 100644 --- a/server/internal/db/domain/entity/query.go +++ b/server/internal/db/domain/entity/query.go @@ -19,6 +19,7 @@ type DataSyncLogQuery struct { } type DbTransferTaskQuery struct { + Name string `json:"name" form:"name"` } type DbTransferLogQuery struct { diff --git a/server/internal/db/infrastructure/persistence/db_transfer.go b/server/internal/db/infrastructure/persistence/db_transfer.go index 99195bdc..2c8f5ba0 100644 --- a/server/internal/db/infrastructure/persistence/db_transfer.go +++ b/server/internal/db/infrastructure/persistence/db_transfer.go @@ -17,8 +17,8 @@ func newDbTransferTaskRepo() repository.DbTransferTask { // 分页获取数据库信息列表 func (d *dbTransferTaskRepoImpl) GetTaskList(condition *entity.DbTransferTaskQuery, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) { - qd := model.NewCond() - //Like("task_name", condition.Name). + qd := model.NewCond(). + Like("task_name", condition.Name) //Eq("status", condition.Status) return d.PageByCondToAny(qd, pageParam, toEntity) } diff --git a/server/pkg/model/login_account.go b/server/pkg/model/login_account.go index 40d841c8..c3cb91b1 100644 --- a/server/pkg/model/login_account.go +++ b/server/pkg/model/login_account.go @@ -3,4 +3,5 @@ package model type LoginAccount struct { Id uint64 Username string + Token string } diff --git a/server/pkg/req/permission_handler.go b/server/pkg/req/permission_handler.go index b7424103..261ae516 100644 --- a/server/pkg/req/permission_handler.go +++ b/server/pkg/req/permission_handler.go @@ -67,6 +67,7 @@ func PermissionHandler(rc *Ctx) error { rc.MetaCtx = contextx.WithLoginAccount(rc.MetaCtx, &model.LoginAccount{ Id: userId, Username: userName, + Token: tokenStr, }) return nil } diff --git a/server/pkg/utils/cryptox/cryptox.go b/server/pkg/utils/cryptox/cryptox.go index 06f00f97..b599a05c 100644 --- a/server/pkg/utils/cryptox/cryptox.go +++ b/server/pkg/utils/cryptox/cryptox.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/aes" "crypto/cipher" + "crypto/des" "crypto/md5" "crypto/rand" "crypto/rsa" @@ -12,6 +13,7 @@ import ( "encoding/hex" "encoding/pem" "errors" + "fmt" "mayfly-go/pkg/cache" "mayfly-go/pkg/logx" "os" @@ -279,6 +281,68 @@ func AesDecryptBase64(data string, key []byte) ([]byte, error) { return AesDecrypt(dataByte, key) } +// DES加密函数 +func DesEncrypt(data, key []byte) (string, error) { + block, err := des.NewTripleDESCipher(key) + if err != nil { + return "", err + } + // 对数据进行填充 + data = pkcs7Padding(data, des.BlockSize) + + // 创建一个初始化向量 + iv := make([]byte, des.BlockSize) + if _, err := rand.Read(iv); err != nil { + return "", err + } + // 创建加密器 + mode := cipher.NewCBCEncrypter(block, iv) + + // 加密 + encrypted := make([]byte, len(data)) + mode.CryptBlocks(encrypted, data) + + // 将IV和加密数据组合 + result := append(iv, encrypted...) + + // 使用Base64编码 + return base64.StdEncoding.EncodeToString(result), nil +} + +func DesDecryptByToken(data string, token string) (string, error) { + key := []byte(token[:24]) + return DesDecrypt(data, key) +} + +func DesDecrypt(data string, key []byte) (string, error) { + // Base64解码 + ciphertext, err := base64.StdEncoding.DecodeString(data) + if err != nil { + return "", err + } + + block, err := des.NewTripleDESCipher(key) + if err != nil { + return "", err + } + + // 确保密文长度正确 + if len(ciphertext) < des.BlockSize { + return "", fmt.Errorf("ciphertext too short") + } + + // 提取IV + iv := ciphertext[:des.BlockSize] + ciphertext = ciphertext[des.BlockSize:] + // 创建解密器 + mode := cipher.NewCBCDecrypter(block, iv) + // 解密仍然用已存在的切片接收结果,无需重新创建切片 + mode.CryptBlocks(ciphertext, ciphertext) + // 去除填充 + res, err := pkcs7UnPadding(ciphertext) + return string(res), err +} + // pkcs7Padding 填充 func pkcs7Padding(data []byte, blockSize int) []byte { //判断缺少几位长度。最少1,最多 blockSize diff --git a/server/pkg/utils/cryptox/cryptox_test.go b/server/pkg/utils/cryptox/cryptox_test.go new file mode 100644 index 00000000..64ebd178 --- /dev/null +++ b/server/pkg/utils/cryptox/cryptox_test.go @@ -0,0 +1,35 @@ +package cryptox + +import ( + "encoding/base64" + "testing" +) + +func TestAesEncrypt(t *testing.T) { + key := []byte("eyJhbGciOiJIUzI1NiIsInR5") + data := []byte("SELECT * FROM \"instruct\" OFFSET 0 LIMIT 25;") + encrypt, err := AesEncrypt(data, key) + if err != nil { + t.Error(err) + } + toString := base64.StdEncoding.EncodeToString(encrypt) + t.Log(toString) + decrypt, err := AesDecrypt(encrypt, key) + + t.Log(string(decrypt)) +} + +func TestDes(t *testing.T) { + key := []byte("eyJhbGciOiJIUzI1NiIsInR5") + data := []byte("SELECT * FROM \"instruct\" OFFSET 0 LIMIT 25;") + encrypt, err := DesEncrypt(data, key) + if err != nil { + t.Error(err) + } + t.Log("encrypt", encrypt) + decrypt, err := DesDecrypt(encrypt, key) + if err != nil { + t.Error(err) + } + t.Log("decrypt", decrypt) +} diff --git a/server/resources/script/sql/mayfly-go.sql b/server/resources/script/sql/mayfly-go.sql index e193eb3e..8ac96014 100644 --- a/server/resources/script/sql/mayfly-go.sql +++ b/server/resources/script/sql/mayfly-go.sql @@ -63,6 +63,7 @@ CREATE TABLE `t_db_transfer_task` ( `modifier` varchar(100) NOT NULL COMMENT '修改人姓名', `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除', + `task_name` varchar(100) NULL comment '任务名', `delete_time` datetime DEFAULT NULL COMMENT '删除时间', `checked_keys` text NOT NULL COMMENT '选中需要迁移的表', `delete_table` tinyint(4) NOT NULL COMMENT '创建表前是否删除表 1是 -1否', diff --git a/server/resources/script/sql/v1.8/v1.8.9.sql b/server/resources/script/sql/v1.8/v1.8.9.sql new file mode 100644 index 00000000..53c3a8af --- /dev/null +++ b/server/resources/script/sql/v1.8/v1.8.9.sql @@ -0,0 +1,2 @@ +ALTER TABLE `t_db_transfer_task` + ADD COLUMN `task_name` varchar(100) NULL comment '任务名' after `delete_time`; \ No newline at end of file