vue-router路由中对query中的参数进行加密

vue-router路由中对query中的参数进行加密

源码地址在文末

在创建路由的时候,添加两个方法

  • stringifyQuery: 序列化传入的query参数,方法可以接收一个对象参数

    new Router的时候传递这个属性,在序列化query参数的就执行这个方法,不会执行默认的方法,序列化后在地址栏显示序列化之后的参数

  • parseQuery: 解析地址栏参数,方法接收一个字符串参数

    new Router的时候传递这个属性,在解析query参数的时候,回执行这个方法,不会在执行默认的方法,

    注: 这个方法只解析path中的参数,或者浏览器刷新的时候的地址栏的参数,不会对在query参数对处理,如:

    1
    2
    3
    4
    5
    6
    7
    8
    ```javascript
        this.$router.push({
            path: "foo?a=123",
            query: {
                b: 345
            }
        })
    ```

    在执行这段代码的时候,parseQuery方法不会对query:{b: 345}进行解析,会解析path:"foo?a=123"中的a=123的字符串

使用方式:

例:

  • router/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
 * 默认在html已经引入了  crypto-js.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);
}

效果:

执行:

1
2
3
4
5
6
this.$router.push({
    path: "/foo",
    query: {
        foo: "App-Foo"
    }
})

地址栏:

1
http://localhost:8081/foo?c3p1R2tZK1AvVENKZTZHRzh3TFhpUT09

在刷新后解析的query

1
{foo: "App-Foo"}

github地址:https://github.com/wukang0718/vueRouterEncryption