天天看點

vue-router路由中對query中的參數進行加密vue-router路由中對query中的參數進行加密

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

繼續閱讀