vue-router路由中對query中的參數進行加密
源碼位址在文末
在建立路由的時候,添加兩個方法
-
stringifyQuery: 序列化傳入的query參數,方法可以接收一個對象參數
在
的時候傳遞這個屬性,在序列化new Router
參數的就執行這個方法,不會執行預設的方法,序列化後在位址欄顯示序列化之後的參數query
-
parseQuery: 解析位址欄參數,方法接收一個字元串參數
在
的時候傳遞這個屬性,在解析new Router
query
參數的時候,回執行這個方法,不會在執行預設的方法,
注: 這個方法隻解析
中的參數,或者浏覽器重新整理的時候的位址欄的參數,不會對在path
參數對處理,如:query
在執行這段代碼的時候,```javascript this.$router.push({ path: "foo?a=123", query: { b: 345 } }) ```
方法不會對parseQuery
進行解析,會解析query:{b: 345}
中的path:"foo?a=123"
的字元串a=123
使用方式:
例:
- router/index.js
import Vue from "vue"
import VueRouter from "vue-router";
import { stringifyQuery, parseQuery } from "./utils/query";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "home",
component: () => import(/* webpackChunkName: "home" */"../views/Home")
},
{
path: "/foo",
name: "foo",
component: () => import(/* webpackChunkName: "foo" */"../views/Foo")
},
{
path: "/bar",
name: "bar",
component: () => import(/* webpackChunkName: "bar" */"../views/Bar")
}
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
stringifyQuery: stringifyQuery,
parseQuery: parseQuery,
routes
});
export default router
- router/utils/query.js
import { getEncryptToBase64 as encrypt, getDecryptByBase64 as decrypt } from "./encryption"
const encodeReserveRE = /[!'()*]/g
const encodeReserveReplacer = c => '%' + c.charCodeAt(0).toString(16)
const commaRE = /%2C/g
const encode = str => encodeURIComponent(str)
.replace(encodeReserveRE, encodeReserveReplacer)
.replace(commaRE, ',')
const decode = decodeURIComponent
/**
* 序列化對象 并加密
* @param {Object} obj
*/
export const stringifyQuery = obj => {
// 序列化方法使用的vue-router中的原方法,詳見vue-router/src/query.js
// 唯一的修改時最後傳回的時候,對參數進行了加密
const res = obj ? Object.keys(obj).map(key => {
const val = obj[key]
if (val === undefined) {
return ''
}
if (val === null) {
return encode(key)
}
if (Array.isArray(val)) {
const result = []
val.forEach(val2 => {
if (val2 === undefined) {
return
}
if (val2 === null) {
result.push(encode(key))
} else {
result.push(encode(key) + '=' + encode(val2))
}
})
return result.join('&')
}
return encode(key) + '=' + encode(val)
}).filter(x => x.length > 0).join('&') : null
return res ? `?${encrypt(res)}` : ''
}
/**
* 解密 解析 字元串參數
* @param {String}} query
*/
export const parseQuery = query => {
// 先對query進行解密
// 在使用vue-router中的解析方法對query進行解析,詳見vue-router/src/query.js
const res = {}
query = query.trim().replace(/^(\?|#|&)/, '')
if (!query) {
return res
}
// 解密
query = decrypt(query);
query.split('&').forEach(param => {
const parts = param.replace(/\+/g, ' ').split('=')
const key = decode(parts.shift())
const val = parts.length > 0
? decode(parts.join('='))
: null
if (res[key] === undefined) {
res[key] = val
} else if (Array.isArray(res[key])) {
res[key].push(val)
} else {
res[key] = [res[key], val]
}
})
return res
}
- router/utils/encryption.js
/*
* 預設在html已經引入了 crypto-js.js 檔案
* 或者npm install crypto-js --save 安裝
* 然後使用import CryptoJS from "crypto-js"
* 加密 解密
*/
const baseCryptoCode = "這一段文字用來做給路由加密的私鑰"; // 私鑰自己指定
const getKeyHex = cryptoCode => CryptoJS.enc.Latin1.parse(cryptoCode || baseCryptoCode);
const getIvHex = () => CryptoJS.enc.Latin1.parse(baseCryptoCode);
/**
* 加密
* @param {String} key
* @param {String} cryptoCode
* @returns {string}
*/
export const getEncrypt = (key, cryptoCode) => {
let keyHex = getKeyHex(cryptoCode);
let ivHex = getIvHex();
try {
key = JSON.stringify(key);
} catch (e) {
console.warn(e);
}
return CryptoJS.AES.encrypt(key, keyHex, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding,
iv: ivHex
}).toString();
}
export const getEncryptToBase64 = (key, cryptoCode) => {
let encryptStr = getEncrypt(key, cryptoCode);
let wordArray = CryptoJS.enc.Utf8.parse(encryptStr);
return CryptoJS.enc.Base64.stringify(wordArray);
}
/**
* 解密
* @param data
* @returns {string}
*/
export const getDecrypt = data => {
let keyHex = getKeyHex();
let ivHex = getIvHex();
let decrypted = CryptoJS.AES.decrypt({
ciphertext: CryptoJS.enc.Base64.parse(data)
}, keyHex, {
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.ZeroPadding,
iv: ivHex
}).toString(CryptoJS.enc.Utf8);
try {
decrypted = JSON.parse(decrypted);
} catch (e) {
console.warn(e);
}
return decrypted
}
/**
* 對base64資料解密 先解析base64,在做解密
* @param {String} data
* @returns {string}
*/
export const getDecryptByBase64 = data => {
let parsedWordArray = CryptoJS.enc.Base64.parse(data);
let decryptStr = parsedWordArray.toString(CryptoJS.enc.Utf8);
return getDecrypt(decryptStr);
}
效果:
執行:
this.$router.push({
path: "/foo",
query: {
foo: "App-Foo"
}
})
位址欄:
http://localhost:8081/foo?c3p1R2tZK1AvVENKZTZHRzh3TFhpUT09
在重新整理後解析的query
{foo: "App-Foo"}
github位址:https://github.com/wukang0718/vueRouterEncryption