Skip to content

Commit f06bdf3

Browse files
committed
feat: implement RSA encryption for login data and update authentication settings
1 parent 74c4545 commit f06bdf3

File tree

10 files changed

+31
-14
lines changed

10 files changed

+31
-14
lines changed

ui/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
"@wecom/jssdk": "^2.3.1",
2828
"axios": "^1.8.4",
2929
"cropperjs": "^1.6.2",
30-
"crypto-js": "^4.2.0",
3130
"dingtalk-jsapi": "^3.1.0",
3231
"echarts": "^5.6.0",
3332
"element-plus": "^2.10.2",
@@ -42,6 +41,7 @@
4241
"mermaid": "^10.9.0",
4342
"moment": "^2.30.1",
4443
"nanoid": "^5.1.5",
44+
"node-forge": "^1.3.1",
4545
"nprogress": "^0.2.0",
4646
"pinia": "^3.0.1",
4747
"recorder-core": "^1.3.25011100",
@@ -64,6 +64,7 @@
6464
"@types/crypto-js": "^4.2.2",
6565
"@types/file-saver": "^2.0.7",
6666
"@types/node": "^22.14.0",
67+
"@types/node-forge": "^1.3.14",
6768
"@types/nprogress": "^0.2.3",
6869
"@vitejs/plugin-vue": "^5.2.3",
6970
"@vitejs/plugin-vue-jsx": "^4.1.2",

ui/src/api/type/chat.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ interface ChatProfile {
1212
// 登录类型
1313
login_value?: Array<string>
1414
max_attempts?: number
15+
rasKey?: string
1516
}
1617

1718
interface ChatUserProfile {

ui/src/api/type/login.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,9 @@ interface LoginRequest {
1111
* 验证码
1212
*/
1313
captcha: string
14+
/**
15+
* 加密数据
16+
*/
17+
encryptedData?: string
1418
}
1519
export type { LoginRequest }

ui/src/stores/modules/chat-user.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ const useChatUserStore = defineStore('chat-user', {
9494
return this.token
9595
})
9696
},
97-
login(request: LoginRequest, loading?: Ref<boolean>) {
97+
login(request: any, loading?: Ref<boolean>) {
9898
return ChatAPI.login(this.accessToken as string, request, loading).then((ok) => {
9999
this.setToken(ok.data.token)
100100
return this.token

ui/src/stores/modules/login.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const useLoginStore = defineStore('login', {
1616
return localStorage.getItem('token')
1717
},
1818

19-
async asyncLogin(data: LoginRequest, loading?: Ref<boolean>) {
19+
async asyncLogin(data: any, loading?: Ref<boolean>) {
2020
return LoginApi.login(data).then((ok) => {
2121
this.token = ok?.data?.token
2222
localStorage.setItem('token', ok?.data?.token)

ui/src/stores/modules/user.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ export interface userStateTypes {
1616
license_is_valid: boolean
1717
edition: 'CE' | 'PE' | 'EE'
1818
workspace_id: string
19-
workspace_list: Array<any>
19+
workspace_list: Array<any>,
20+
rasKey: string
2021
}
2122

2223
const useUserStore = defineStore('user', {
@@ -27,6 +28,7 @@ const useUserStore = defineStore('user', {
2728
edition: 'CE',
2829
workspace_id: '',
2930
workspace_list: [],
31+
rasKey: '',
3032
}),
3133
actions: {
3234
getLanguage() {
@@ -140,6 +142,7 @@ const useUserStore = defineStore('user', {
140142
this.license_is_valid = ok.data.license_is_valid
141143
this.edition = ok.data.edition
142144
this.version = ok.data.version
145+
this.rasKey = ok.data.ras
143146
const theme = useThemeStore()
144147
if (this.isEE() || this.isPE()) {
145148
await theme.theme()

ui/src/views/chat/user-login/index.vue

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ import QrCodeTab from '@/views/chat/user-login/scanCompinents/QrCodeTab.vue'
180180
import {MsgConfirm, MsgError} from '@/utils/message.ts'
181181
import PasswordAuth from '@/views/chat/auth/component/password.vue'
182182
import {isAppIcon} from '@/utils/common'
183-
import CryptoJS from "crypto-js";
183+
import forge from "node-forge";
184184
185185
useResize()
186186
const router = useRouter()
@@ -250,8 +250,13 @@ const loginHandle = () => {
250250
})
251251
})
252252
} else {
253-
loginForm.value.password = CryptoJS.MD5(loginForm.value.password.trim()).toString(CryptoJS.enc.Hex)
254-
chatUser.login(loginForm.value).then((ok) => {
253+
const publicKey = forge.pki.publicKeyFromPem(chatUser?.chat_profile?.rasKey as any);
254+
const encrypted = publicKey.encrypt(JSON.stringify(loginForm.value), 'RSAES-PKCS1-V1_5');
255+
const encryptedBase64 = forge.util.encode64(encrypted);
256+
chatUser.login({
257+
encryptedData: encryptedBase64,
258+
username: loginForm.value.username
259+
}).then((ok) => {
255260
router.push({
256261
name: 'chat',
257262
params: {accessToken: chatUser.accessToken},

ui/src/views/login/index.vue

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ import QrCodeTab from '@/views/login/scanCompinents/QrCodeTab.vue'
141141
import {MsgConfirm, MsgError} from '@/utils/message.ts'
142142
import * as dd from 'dingtalk-jsapi'
143143
import {loadScript} from '@/utils/common'
144-
import CryptoJS from 'crypto-js';
144+
import forge from 'node-forge';
145145
146146
const router = useRouter()
147147
const {login, user, theme} = useStore()
@@ -200,9 +200,11 @@ const loginHandle = () => {
200200
loading.value = false
201201
})
202202
} else {
203-
loginForm.value.password = CryptoJS.MD5(loginForm.value.password.trim()).toString(CryptoJS.enc.Hex)
203+
const publicKey = forge.pki.publicKeyFromPem(user.rasKey);
204+
const encrypted = publicKey.encrypt(JSON.stringify(loginForm.value), 'RSAES-PKCS1-V1_5');
205+
const encryptedBase64 = forge.util.encode64(encrypted);
204206
login
205-
.asyncLogin(loginForm.value)
207+
.asyncLogin({encryptedData: encryptedBase64, username: loginForm.value.username})
206208
.then(() => {
207209
locale.value = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
208210
localStorage.setItem('workspace_id', 'default')
@@ -298,7 +300,7 @@ onBeforeMount(() => {
298300
} else {
299301
authSetting.value = {
300302
max_attempts: 1,
301-
default_value: 'password',
303+
default_value: 'LOCAL',
302304
}
303305
}
304306
const params = route.query
@@ -315,7 +317,7 @@ onBeforeMount(() => {
315317
} else {
316318
authSetting.value = {
317319
max_attempts: 1,
318-
default_value: 'password',
320+
default_value: 'LOCAL',
319321
}
320322
}
321323
})
@@ -351,7 +353,7 @@ const newDefaultSlogan = computed(() => {
351353
})
352354
353355
function redirectAuth(authType: string, needMessage: boolean = true) {
354-
if (authType === 'LDAP' || authType === '' || authType === 'password') {
356+
if (authType === 'LDAP' || authType === '' || authType === 'LOCAL') {
355357
return
356358
}
357359
authApi.getLoginViewAuthSetting(authType, loading).then((res: any) => {

ui/src/views/system-setting/authentication/component/Setting.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const authFormRef = ref<FormInstance>();
8484
8585
8686
const form = ref<any>({
87-
default_value: 'password',
87+
default_value: 'LOCAL',
8888
max_attempts: 1,
8989
})
9090

ui/src/workflow/nodes/image-to-video/index.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
:placeholder="
172172
$t('views.applicationWorkflow.nodes.imageToVideoGenerate.last_frame.requiredMessage')
173173
"
174+
clearable
174175
v-model="form_data.last_frame_url"
175176
/>
176177
</el-form-item>

0 commit comments

Comments
 (0)