feat: implement RSA encryption for login data and update authentication settings
parent
74c454532d
commit
f06bdf3ee5
|
|
@ -27,7 +27,6 @@
|
||||||
"@wecom/jssdk": "^2.3.1",
|
"@wecom/jssdk": "^2.3.1",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"cropperjs": "^1.6.2",
|
"cropperjs": "^1.6.2",
|
||||||
"crypto-js": "^4.2.0",
|
|
||||||
"dingtalk-jsapi": "^3.1.0",
|
"dingtalk-jsapi": "^3.1.0",
|
||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
"element-plus": "^2.10.2",
|
"element-plus": "^2.10.2",
|
||||||
|
|
@ -42,6 +41,7 @@
|
||||||
"mermaid": "^10.9.0",
|
"mermaid": "^10.9.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
|
"node-forge": "^1.3.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^3.0.1",
|
"pinia": "^3.0.1",
|
||||||
"recorder-core": "^1.3.25011100",
|
"recorder-core": "^1.3.25011100",
|
||||||
|
|
@ -64,6 +64,7 @@
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/file-saver": "^2.0.7",
|
"@types/file-saver": "^2.0.7",
|
||||||
"@types/node": "^22.14.0",
|
"@types/node": "^22.14.0",
|
||||||
|
"@types/node-forge": "^1.3.14",
|
||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@vitejs/plugin-vue": "^5.2.3",
|
"@vitejs/plugin-vue": "^5.2.3",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
"@vitejs/plugin-vue-jsx": "^4.1.2",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ interface ChatProfile {
|
||||||
// 登录类型
|
// 登录类型
|
||||||
login_value?: Array<string>
|
login_value?: Array<string>
|
||||||
max_attempts?: number
|
max_attempts?: number
|
||||||
|
rasKey?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ChatUserProfile {
|
interface ChatUserProfile {
|
||||||
|
|
|
||||||
|
|
@ -11,5 +11,9 @@ interface LoginRequest {
|
||||||
* 验证码
|
* 验证码
|
||||||
*/
|
*/
|
||||||
captcha: string
|
captcha: string
|
||||||
|
/**
|
||||||
|
* 加密数据
|
||||||
|
*/
|
||||||
|
encryptedData?: string
|
||||||
}
|
}
|
||||||
export type { LoginRequest }
|
export type { LoginRequest }
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ const useChatUserStore = defineStore('chat-user', {
|
||||||
return this.token
|
return this.token
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
login(request: LoginRequest, loading?: Ref<boolean>) {
|
login(request: any, loading?: Ref<boolean>) {
|
||||||
return ChatAPI.login(this.accessToken as string, request, loading).then((ok) => {
|
return ChatAPI.login(this.accessToken as string, request, loading).then((ok) => {
|
||||||
this.setToken(ok.data.token)
|
this.setToken(ok.data.token)
|
||||||
return this.token
|
return this.token
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const useLoginStore = defineStore('login', {
|
||||||
return localStorage.getItem('token')
|
return localStorage.getItem('token')
|
||||||
},
|
},
|
||||||
|
|
||||||
async asyncLogin(data: LoginRequest, loading?: Ref<boolean>) {
|
async asyncLogin(data: any, loading?: Ref<boolean>) {
|
||||||
return LoginApi.login(data).then((ok) => {
|
return LoginApi.login(data).then((ok) => {
|
||||||
this.token = ok?.data?.token
|
this.token = ok?.data?.token
|
||||||
localStorage.setItem('token', ok?.data?.token)
|
localStorage.setItem('token', ok?.data?.token)
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ export interface userStateTypes {
|
||||||
license_is_valid: boolean
|
license_is_valid: boolean
|
||||||
edition: 'CE' | 'PE' | 'EE'
|
edition: 'CE' | 'PE' | 'EE'
|
||||||
workspace_id: string
|
workspace_id: string
|
||||||
workspace_list: Array<any>
|
workspace_list: Array<any>,
|
||||||
|
rasKey: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const useUserStore = defineStore('user', {
|
const useUserStore = defineStore('user', {
|
||||||
|
|
@ -27,6 +28,7 @@ const useUserStore = defineStore('user', {
|
||||||
edition: 'CE',
|
edition: 'CE',
|
||||||
workspace_id: '',
|
workspace_id: '',
|
||||||
workspace_list: [],
|
workspace_list: [],
|
||||||
|
rasKey: '',
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
getLanguage() {
|
getLanguage() {
|
||||||
|
|
@ -140,6 +142,7 @@ const useUserStore = defineStore('user', {
|
||||||
this.license_is_valid = ok.data.license_is_valid
|
this.license_is_valid = ok.data.license_is_valid
|
||||||
this.edition = ok.data.edition
|
this.edition = ok.data.edition
|
||||||
this.version = ok.data.version
|
this.version = ok.data.version
|
||||||
|
this.rasKey = ok.data.ras
|
||||||
const theme = useThemeStore()
|
const theme = useThemeStore()
|
||||||
if (this.isEE() || this.isPE()) {
|
if (this.isEE() || this.isPE()) {
|
||||||
await theme.theme()
|
await theme.theme()
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ import QrCodeTab from '@/views/chat/user-login/scanCompinents/QrCodeTab.vue'
|
||||||
import {MsgConfirm, MsgError} from '@/utils/message.ts'
|
import {MsgConfirm, MsgError} from '@/utils/message.ts'
|
||||||
import PasswordAuth from '@/views/chat/auth/component/password.vue'
|
import PasswordAuth from '@/views/chat/auth/component/password.vue'
|
||||||
import {isAppIcon} from '@/utils/common'
|
import {isAppIcon} from '@/utils/common'
|
||||||
import CryptoJS from "crypto-js";
|
import forge from "node-forge";
|
||||||
|
|
||||||
useResize()
|
useResize()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
@ -250,8 +250,13 @@ const loginHandle = () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
loginForm.value.password = CryptoJS.MD5(loginForm.value.password.trim()).toString(CryptoJS.enc.Hex)
|
const publicKey = forge.pki.publicKeyFromPem(chatUser?.chat_profile?.rasKey as any);
|
||||||
chatUser.login(loginForm.value).then((ok) => {
|
const encrypted = publicKey.encrypt(JSON.stringify(loginForm.value), 'RSAES-PKCS1-V1_5');
|
||||||
|
const encryptedBase64 = forge.util.encode64(encrypted);
|
||||||
|
chatUser.login({
|
||||||
|
encryptedData: encryptedBase64,
|
||||||
|
username: loginForm.value.username
|
||||||
|
}).then((ok) => {
|
||||||
router.push({
|
router.push({
|
||||||
name: 'chat',
|
name: 'chat',
|
||||||
params: {accessToken: chatUser.accessToken},
|
params: {accessToken: chatUser.accessToken},
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ import QrCodeTab from '@/views/login/scanCompinents/QrCodeTab.vue'
|
||||||
import {MsgConfirm, MsgError} from '@/utils/message.ts'
|
import {MsgConfirm, MsgError} from '@/utils/message.ts'
|
||||||
import * as dd from 'dingtalk-jsapi'
|
import * as dd from 'dingtalk-jsapi'
|
||||||
import {loadScript} from '@/utils/common'
|
import {loadScript} from '@/utils/common'
|
||||||
import CryptoJS from 'crypto-js';
|
import forge from 'node-forge';
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const {login, user, theme} = useStore()
|
const {login, user, theme} = useStore()
|
||||||
|
|
@ -200,9 +200,11 @@ const loginHandle = () => {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
loginForm.value.password = CryptoJS.MD5(loginForm.value.password.trim()).toString(CryptoJS.enc.Hex)
|
const publicKey = forge.pki.publicKeyFromPem(user.rasKey);
|
||||||
|
const encrypted = publicKey.encrypt(JSON.stringify(loginForm.value), 'RSAES-PKCS1-V1_5');
|
||||||
|
const encryptedBase64 = forge.util.encode64(encrypted);
|
||||||
login
|
login
|
||||||
.asyncLogin(loginForm.value)
|
.asyncLogin({encryptedData: encryptedBase64, username: loginForm.value.username})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
locale.value = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
|
locale.value = localStorage.getItem('MaxKB-locale') || getBrowserLang() || 'en-US'
|
||||||
localStorage.setItem('workspace_id', 'default')
|
localStorage.setItem('workspace_id', 'default')
|
||||||
|
|
@ -298,7 +300,7 @@ onBeforeMount(() => {
|
||||||
} else {
|
} else {
|
||||||
authSetting.value = {
|
authSetting.value = {
|
||||||
max_attempts: 1,
|
max_attempts: 1,
|
||||||
default_value: 'password',
|
default_value: 'LOCAL',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const params = route.query
|
const params = route.query
|
||||||
|
|
@ -315,7 +317,7 @@ onBeforeMount(() => {
|
||||||
} else {
|
} else {
|
||||||
authSetting.value = {
|
authSetting.value = {
|
||||||
max_attempts: 1,
|
max_attempts: 1,
|
||||||
default_value: 'password',
|
default_value: 'LOCAL',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -351,7 +353,7 @@ const newDefaultSlogan = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
function redirectAuth(authType: string, needMessage: boolean = true) {
|
function redirectAuth(authType: string, needMessage: boolean = true) {
|
||||||
if (authType === 'LDAP' || authType === '' || authType === 'password') {
|
if (authType === 'LDAP' || authType === '' || authType === 'LOCAL') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
authApi.getLoginViewAuthSetting(authType, loading).then((res: any) => {
|
authApi.getLoginViewAuthSetting(authType, loading).then((res: any) => {
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ const authFormRef = ref<FormInstance>();
|
||||||
|
|
||||||
|
|
||||||
const form = ref<any>({
|
const form = ref<any>({
|
||||||
default_value: 'password',
|
default_value: 'LOCAL',
|
||||||
max_attempts: 1,
|
max_attempts: 1,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@
|
||||||
:placeholder="
|
:placeholder="
|
||||||
$t('views.applicationWorkflow.nodes.imageToVideoGenerate.last_frame.requiredMessage')
|
$t('views.applicationWorkflow.nodes.imageToVideoGenerate.last_frame.requiredMessage')
|
||||||
"
|
"
|
||||||
|
clearable
|
||||||
v-model="form_data.last_frame_url"
|
v-model="form_data.last_frame_url"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue