vue2-client 1.20.92 → 1.20.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/constants/crypto.js +5 -0
- package/src/pages/login/Login.vue +2 -9
- package/src/pages/login/LoginV3.vue +2 -9
- package/src/utils/EncryptUtil.js +26 -8
- package/src/utils/login.js +49 -13
- package/vue.config.js +10 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vue2-client",
|
|
3
|
-
"version": "1.20.
|
|
3
|
+
"version": "1.20.93",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve --no-eslint",
|
|
@@ -113,4 +113,4 @@
|
|
|
113
113
|
"not dead",
|
|
114
114
|
"not ie 11"
|
|
115
115
|
]
|
|
116
|
-
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 与会话加密对应的 RSA 私钥,与 af-system-vue-web .env 中 VITE_RSA_PRIVATE_KEY 保持一致
|
|
3
|
+
*/
|
|
4
|
+
export const RSA_PRIVATE_KEY =
|
|
5
|
+
'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIRrmftLDHCQqREEJ132Onu+W3vmFbdF7QD751SrcDDGDTfzuz1zBuElvkHhuDBb7KZkXrCIe+MhvX2IvxcLObl3faX+evYlnfj2HRbF0hIpQLuIq22tL06ZcV5w7wqLxUZRpFElIFm8gZTkUvfKXVuHw89e4daDVhU5hK3GHNGTAgMBAAECgYABiINrFaE1E8pkBYx1JJA5yuhL73aUktfd2TeCU00vFg6kyrWCI85Sa2RKu/6CJNZWeOFgdubEUv7a22tRrNIZb3yUMaqtTwSso78mspIOJqjWXTkTH9WPElfTcdpdIse/lgZtPz6egxkuhadSvwrM9Y6NgusiW/5+x95Ct08iOQJBAN5aK+7uISURvGQj2EaRtgGEd8+d4oHl+BYvvTeG3qSgUikHQW3j0sp4gXPw2kxw6sjVgLFOc4FB6LGqwzOTzokCQQCYdYG8ty3Uo/ebUlNzeJFxHXjy/KvBSytAUzAXkRu3nZrkEaPQsi3dgOkZgk+F1fMDzfQ4EbDIU6xvqOoZXHg7AkATCW9XfoXR8anKfRMoP5Nwn9HOMbtR2cmaxK2TknV/bMZ8AsYETYwfj5+tuIJIJybC2RyykX/sIiN1CqS5xr7ZAkArj19rMRdaKyMi8MnBM1Cy9g3Jt2HHj5ejAGG8SgyWUOShh1y70z0BjcSMMkxQXAncK2s83ekZw7aADM4eQupjAkARRgTwwMOnn3IoKmQusKhZk0uxilZ4Zc2LH6Z4GiWnvteM0W8Zw4Z1lJUcjgQq3dGqL2RdmzeQZ+HgPIOXrZVK'
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
<script>
|
|
56
56
|
import CommonLayout from '@vue2-client/layouts/CommonLayout'
|
|
57
57
|
import { getRoutesConfig, login, V4Login } from '@vue2-client/services/user'
|
|
58
|
+
import { setV4AccessToken } from '@vue2-client/utils/login'
|
|
58
59
|
import { setAuthorization } from '@vue2-client/utils/request'
|
|
59
60
|
import { loadRoutes, funcToRouterOA, funcToRouter } from '@vue2-client/utils/routerUtil'
|
|
60
61
|
import { mapMutations, mapState } from 'vuex'
|
|
@@ -131,7 +132,7 @@ export default {
|
|
|
131
132
|
}
|
|
132
133
|
},
|
|
133
134
|
afterLoginV4 (res) {
|
|
134
|
-
|
|
135
|
+
setV4AccessToken(res)
|
|
135
136
|
let data = res.resources
|
|
136
137
|
if (data.data) {
|
|
137
138
|
data = data.data
|
|
@@ -224,14 +225,6 @@ export default {
|
|
|
224
225
|
const dateAfter = new Date(timestamp)
|
|
225
226
|
setAuthorization({ token: data, expireAt: dateAfter })
|
|
226
227
|
}
|
|
227
|
-
},
|
|
228
|
-
setV4AccessToken (res) {
|
|
229
|
-
localStorage.setItem(ACCESS_TOKEN, res.access_token)
|
|
230
|
-
let timestamp = new Date().getTime()// 当前的时间戳
|
|
231
|
-
timestamp = timestamp + res.expire * 60 * 1000
|
|
232
|
-
// 格式化时间获取年月日, 登陆过期时间
|
|
233
|
-
const dateAfter = new Date(timestamp)
|
|
234
|
-
setAuthorization({ token: res.access_token, expireAt: dateAfter })
|
|
235
228
|
}
|
|
236
229
|
}
|
|
237
230
|
}
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
<script>
|
|
56
56
|
import CommonLayout from '@vue2-client/layouts/CommonLayout'
|
|
57
57
|
import { getRoutesConfig, login, V4Login } from '@vue2-client/services/user'
|
|
58
|
+
import { setV4AccessToken } from '@vue2-client/utils/login'
|
|
58
59
|
import { setAuthorization } from '@vue2-client/utils/request'
|
|
59
60
|
import { loadRoutes, funcToRouterOA, funcToRouter } from '@vue2-client/utils/routerUtil'
|
|
60
61
|
import { mapMutations, mapState } from 'vuex'
|
|
@@ -130,7 +131,7 @@ export default {
|
|
|
130
131
|
}
|
|
131
132
|
},
|
|
132
133
|
afterLoginV4 (res) {
|
|
133
|
-
|
|
134
|
+
setV4AccessToken(res)
|
|
134
135
|
let data = res.resources
|
|
135
136
|
if (data.data) {
|
|
136
137
|
data = data.data
|
|
@@ -223,14 +224,6 @@ export default {
|
|
|
223
224
|
const dateAfter = new Date(timestamp)
|
|
224
225
|
setAuthorization({ token: data, expireAt: dateAfter })
|
|
225
226
|
}
|
|
226
|
-
},
|
|
227
|
-
setV4AccessToken (res) {
|
|
228
|
-
localStorage.setItem(ACCESS_TOKEN, res.access_token)
|
|
229
|
-
let timestamp = new Date().getTime()// 当前的时间戳
|
|
230
|
-
timestamp = timestamp + res.expire * 60 * 1000
|
|
231
|
-
// 格式化时间获取年月日, 登陆过期时间
|
|
232
|
-
const dateAfter = new Date(timestamp)
|
|
233
|
-
setAuthorization({ token: res.access_token, expireAt: dateAfter })
|
|
234
227
|
}
|
|
235
228
|
}
|
|
236
229
|
}
|
package/src/utils/EncryptUtil.js
CHANGED
|
@@ -7,7 +7,7 @@ export default {
|
|
|
7
7
|
* @param word
|
|
8
8
|
* @returns {*}
|
|
9
9
|
*/
|
|
10
|
-
AESEncrypt
|
|
10
|
+
AESEncrypt(word, encryKey) {
|
|
11
11
|
const key = CryptoJS.enc.Utf8.parse(encryKey)
|
|
12
12
|
const srcs = CryptoJS.enc.Utf8.parse(word)
|
|
13
13
|
const encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
|
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
* @param word
|
|
19
19
|
* @returns {*}
|
|
20
20
|
*/
|
|
21
|
-
AESDecrypt
|
|
21
|
+
AESDecrypt(word, encryKey) {
|
|
22
22
|
const key = CryptoJS.enc.Utf8.parse(encryKey)
|
|
23
23
|
const decrypt = CryptoJS.AES.decrypt(word, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
|
|
24
24
|
const ret = CryptoJS.enc.Utf8.stringify(decrypt).toString()
|
|
@@ -33,7 +33,7 @@ export default {
|
|
|
33
33
|
* @param word
|
|
34
34
|
* @returns {*}
|
|
35
35
|
*/
|
|
36
|
-
RSAEncrypt
|
|
36
|
+
RSAEncrypt(word) {
|
|
37
37
|
const encrypt = new RsaEncryptJS()
|
|
38
38
|
encrypt.setPublicKey('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqPvovSfXcwBbW8cKMCgwqNpsYuzF8RPAPFb7LGsnVo44JhM/xxzDyzoYtdfNmtbIuKVi9PzIsyp6rg+09gbuI6UGwBZ5DWBDBMqv5MPdOF5dCQkB2Bbr5yPfURPENypUz+pBFBg41d+BC+rwRiXELwKy7Y9caD/MtJyHydj8OUwIDAQAB')
|
|
39
39
|
const resdata = encrypt.encrypt(word)
|
|
@@ -44,14 +44,32 @@ export default {
|
|
|
44
44
|
* @param word
|
|
45
45
|
* @returns {*}
|
|
46
46
|
*/
|
|
47
|
-
RSADecrypt
|
|
47
|
+
RSADecrypt(word) {
|
|
48
48
|
const encrypt = new RsaEncryptJS()
|
|
49
49
|
encrypt.setPrivateKey('MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKo++i9J9dzAFtbxwowKDCo2mxi7MXxE8A8VvssaydWjjgmEz/HHMPLOhi1182a1si4pWL0/MizKnquD7T2Bu4jpQbAFnkNYEMEyq/kw904Xl0JCQHYFuvnI99RE8Q3KlTP6kEUGDjV34EL6vBGJcQvArLtj1xoP8y0nIfJ2Pw5TAgMBAAECgYAGGB8IllMwxceLhjf6n1l0IWRH7FuHIUieoZ6k0p6rASHSgWiYNRMxfecbtX8zDAoG0QAWNi7rn40ygpR5gS1fWDAKhmnhKgQIT6wW0VmD4hraaeyP78iy8BLhlvblri2nCPIhDH5+l96v7D47ZZi3ZSOzcj89s1eS/k7/N4peEQJBAPEtGGJY+lBoCxQMhGyzuzDmgcS1Un1ZE2pt+XNCVl2b+T8fxWJH3tRRR8wOY5uvtPiK1HM/IjT0T5qwQeH8Yk0CQQC0tcv3d/bDb7bOe9QzUFDQkUSpTdPWAgMX2OVPxjdq3Sls9oA5+fGNYEy0OgyqTjde0b4iRzlD1O0OhLqPSUMfAkEAh5FIvqezdRU2/PsYSR4yoAdCdLdT+h/jGRVefhqQ/6eYUJJkWp15tTFHQX3pIe9/s6IeT/XyHYAjaxmevxAmlQJBAKSdhvQjf9KAjZKDEsa7vyJ/coCXuQUWSCMNHbcR5aGfXgE4e45UtUoIE1eKGcd6AM6LWhx3rR6xdFDpb9je8BkCQB0SpevGfOQkMk5i8xkEt9eeYP0fi8nv6eOUcK96EXbzs4jV2SAoQJ9oJegPtPROHbhIvVUmNQTbuP10Yjg59+8=')
|
|
50
50
|
const resdata = encrypt.decrypt(word)
|
|
51
51
|
return JSON.parse(resdata.toString())
|
|
52
52
|
},
|
|
53
|
+
/**
|
|
54
|
+
* RSA 私钥解密,返回明文字符串(不做 JSON 解析)
|
|
55
|
+
*
|
|
56
|
+
* @param {string} encryptedData Base64 密文
|
|
57
|
+
* @param {string} privateKey PKCS#8 格式的私钥
|
|
58
|
+
* @returns {string|null} 解密失败时返回 null
|
|
59
|
+
*/
|
|
60
|
+
RSADecryptRaw(encryptedData, privateKey) {
|
|
61
|
+
try {
|
|
62
|
+
const encrypt = new RsaEncryptJS()
|
|
63
|
+
encrypt.setPrivateKey(privateKey)
|
|
64
|
+
const decrypted = encrypt.decrypt(encryptedData)
|
|
65
|
+
if (!decrypted) return null
|
|
66
|
+
return decrypted
|
|
67
|
+
} catch {
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
},
|
|
53
71
|
|
|
54
|
-
AESEncryptCBC
|
|
72
|
+
AESEncryptCBC(data, CRYPTO_KEY) {
|
|
55
73
|
// 生成随机IV(每次加密不同)
|
|
56
74
|
const iv = CryptoJS.lib.WordArray.random(16)
|
|
57
75
|
|
|
@@ -79,7 +97,7 @@ export default {
|
|
|
79
97
|
* @param hexKey 十六进制格式的加密密钥
|
|
80
98
|
* @returns 解密后的原始字符串
|
|
81
99
|
*/
|
|
82
|
-
AESDecryptCBC
|
|
100
|
+
AESDecryptCBC(combinedText, hexKey) {
|
|
83
101
|
try {
|
|
84
102
|
// 分离 IV 和 密文
|
|
85
103
|
const parts = combinedText.split(':')
|
|
@@ -114,7 +132,7 @@ export default {
|
|
|
114
132
|
* @param hexKey 十六进制格式的密钥
|
|
115
133
|
* @returns 解密后的字符串,失败时返回null
|
|
116
134
|
*/
|
|
117
|
-
safeAESDecryptCBC
|
|
135
|
+
safeAESDecryptCBC(combinedText, hexKey) {
|
|
118
136
|
try {
|
|
119
137
|
return this.AESDecryptCBC(combinedText, hexKey)
|
|
120
138
|
} catch {
|
|
@@ -129,7 +147,7 @@ export default {
|
|
|
129
147
|
* @param sessionKey 会话密钥
|
|
130
148
|
* @returns 解密后的数据,失败时返回原数据
|
|
131
149
|
*/
|
|
132
|
-
decryptResponse
|
|
150
|
+
decryptResponse(responseData, sessionKey) {
|
|
133
151
|
try {
|
|
134
152
|
let dataStr = ''
|
|
135
153
|
|
package/src/utils/login.js
CHANGED
|
@@ -9,9 +9,12 @@ import { message } from 'ant-design-vue'
|
|
|
9
9
|
import {
|
|
10
10
|
ACCESS_TOKEN,
|
|
11
11
|
V4_ACCESS_TOKEN,
|
|
12
|
+
V4_SESSION_KEY,
|
|
12
13
|
} from '@vue2-client/store/mutation-types'
|
|
13
14
|
import { setAuthorization } from '@vue2-client/utils/request'
|
|
14
15
|
import { loginGen } from '@vue2-client/base-client/plugins/GetLoginInfoService'
|
|
16
|
+
import { RSA_PRIVATE_KEY } from '@vue2-client/constants/crypto'
|
|
17
|
+
import EncryptUtil from '@vue2-client/utils/EncryptUtil'
|
|
15
18
|
// 认证类型
|
|
16
19
|
const AUTH_TYPE = {
|
|
17
20
|
BEARER: 'Bearer',
|
|
@@ -21,7 +24,7 @@ const AUTH_TYPE = {
|
|
|
21
24
|
AUTH2: 'auth2',
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
export function checkSingleAuthorization
|
|
27
|
+
export function checkSingleAuthorization(authType = AUTH_TYPE.BEARER, token) {
|
|
25
28
|
switch (authType) {
|
|
26
29
|
case AUTH_TYPE.BEARER:
|
|
27
30
|
if (localStorage.getItem(V4_ACCESS_TOKEN)) {
|
|
@@ -39,7 +42,7 @@ export function checkSingleAuthorization (authType = AUTH_TYPE.BEARER, token) {
|
|
|
39
42
|
return false
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
function setSingleAuthorization
|
|
45
|
+
function setSingleAuthorization(auth, authType = AUTH_TYPE.BEARER) {
|
|
43
46
|
switch (authType) {
|
|
44
47
|
case AUTH_TYPE.BEARER:
|
|
45
48
|
localStorage.setItem(V4_ACCESS_TOKEN, 'Bearer ' + auth.token)
|
|
@@ -52,7 +55,7 @@ function setSingleAuthorization (auth, authType = AUTH_TYPE.BEARER) {
|
|
|
52
55
|
}
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
function setAccessToken
|
|
58
|
+
function setAccessToken(data) {
|
|
56
59
|
if (data) {
|
|
57
60
|
localStorage.setItem(ACCESS_TOKEN, data)
|
|
58
61
|
let timestamp = new Date().getTime() // 当前的时间戳
|
|
@@ -63,7 +66,7 @@ function setAccessToken (data) {
|
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
function afterGeneral
|
|
69
|
+
function afterGeneral(result, options) {
|
|
67
70
|
return new Promise((resolve) => {
|
|
68
71
|
const { password, store } = options
|
|
69
72
|
const user = Object.assign(
|
|
@@ -93,7 +96,7 @@ function afterGeneral (result, options) {
|
|
|
93
96
|
})
|
|
94
97
|
}
|
|
95
98
|
|
|
96
|
-
function afterLogin
|
|
99
|
+
function afterLogin(res, options) {
|
|
97
100
|
const { name, password, store, router, pathname } = options
|
|
98
101
|
const setting = store.state.setting
|
|
99
102
|
const loginRes = res.states
|
|
@@ -138,7 +141,7 @@ function afterLogin (res, options) {
|
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
|
|
141
|
-
function afterLoginV4
|
|
144
|
+
function afterLoginV4(res, option) {
|
|
142
145
|
const { router, pathname } = option
|
|
143
146
|
setV4AccessToken(res)
|
|
144
147
|
let data = res.resources
|
|
@@ -154,16 +157,49 @@ function afterLoginV4 (res, option) {
|
|
|
154
157
|
})
|
|
155
158
|
}
|
|
156
159
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
function unwrapV4LoginPayload(res) {
|
|
161
|
+
if (!res || typeof res !== 'object') return null
|
|
162
|
+
if (res.access_token !== undefined && res.access_token !== null) return res
|
|
163
|
+
if (
|
|
164
|
+
res.data &&
|
|
165
|
+
typeof res.data === 'object' &&
|
|
166
|
+
res.data.access_token !== undefined &&
|
|
167
|
+
res.data.access_token !== null
|
|
168
|
+
) {
|
|
169
|
+
return res.data
|
|
170
|
+
}
|
|
171
|
+
return null
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function getWebConfigFromStorage() {
|
|
175
|
+
try {
|
|
176
|
+
const str = localStorage.getItem(process.env.VUE_APP_WEB_CONFIG_KEY)
|
|
177
|
+
return str ? JSON.parse(str) : {}
|
|
178
|
+
} catch {
|
|
179
|
+
return {}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** 解析登录接口返回的 session 并写入 v4-session-key(受 webConfig.requestEncrypt 控制) */
|
|
184
|
+
export function setV4SessionKey(res) {
|
|
185
|
+
const webConfig = getWebConfigFromStorage()
|
|
186
|
+
if (!res?.session || !webConfig?.setting?.requestEncrypt) return
|
|
187
|
+
const sessionKey = EncryptUtil.RSADecryptRaw(res.session, RSA_PRIVATE_KEY)
|
|
188
|
+
if (sessionKey) localStorage.setItem(V4_SESSION_KEY, sessionKey)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function setV4AccessToken(res) {
|
|
192
|
+
const payload = unwrapV4LoginPayload(res)
|
|
193
|
+
if (!payload?.access_token) return
|
|
194
|
+
localStorage.setItem(ACCESS_TOKEN, payload.access_token)
|
|
195
|
+
let timestamp = new Date().getTime() // 当前的时间戳
|
|
196
|
+
timestamp += (payload.expire ?? 0) * 60 * 1000
|
|
162
197
|
const dateAfter = new Date(timestamp)
|
|
163
|
-
setAuthorization({ token:
|
|
198
|
+
setAuthorization({ token: payload.access_token, expireAt: dateAfter })
|
|
199
|
+
setV4SessionKey(payload)
|
|
164
200
|
}
|
|
165
201
|
|
|
166
|
-
export function startLogin
|
|
202
|
+
export function startLogin(options) {
|
|
167
203
|
const { name, password, store } = options
|
|
168
204
|
const setting = store.state.setting
|
|
169
205
|
switch (setting.compatible) {
|
package/vue.config.js
CHANGED
|
@@ -11,13 +11,13 @@ const productionGzipExtensions = ['js', 'css']
|
|
|
11
11
|
const isProd = process.env.NODE_ENV === 'production'
|
|
12
12
|
|
|
13
13
|
// v4 产品演示
|
|
14
|
-
const liuli = '
|
|
15
|
-
const v3Server = '
|
|
16
|
-
const geoserver = '
|
|
14
|
+
const liuli = 'https://192.168.50.105:31467'
|
|
15
|
+
const v3Server = 'https://192.168.50.105:31467'
|
|
16
|
+
const geoserver = 'https://192.168.50.105:31467'
|
|
17
17
|
// const gateway = 'http://192.168.50.67:31467'
|
|
18
18
|
// const testUpload = 'http://123.60.214.109:8406'
|
|
19
19
|
const OSSServerDev = 'http://192.168.50.67:30351'
|
|
20
|
-
const revenue = '
|
|
20
|
+
const revenue = 'https://192.168.50.105:31467'
|
|
21
21
|
// const revenue = 'http://127.0.0.1:31467'
|
|
22
22
|
// const OSSServerProd = 'http://192.168.50.67:31351'
|
|
23
23
|
// const testUploadLocal = 'http://127.0.0.1:9001'
|
|
@@ -225,13 +225,13 @@ module.exports = {
|
|
|
225
225
|
css: {
|
|
226
226
|
extract: !isProd
|
|
227
227
|
? {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
filename: 'css/[name].css',
|
|
229
|
+
chunkFilename: 'css/[name].css',
|
|
230
|
+
ignoreOrder: true
|
|
231
|
+
}
|
|
232
232
|
: {
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
ignoreOrder: true
|
|
234
|
+
},
|
|
235
235
|
loaderOptions: {
|
|
236
236
|
less: {
|
|
237
237
|
lessOptions: {
|