vue-router中query参数做自动加密、解密

vue-router 插件,对vue-router使用中query参数做自动加密、解密

仓库地址

​ github: https://github.com/wukang0718/vueRouterEncryption

​ gitee: https://gitee.com/wu_kang0718/vueRouterEncryption

使用方式

  1. 加密需要依赖 crypto-js 库,安装:

npm

1
npm install crypto-js --save

yarn

1
yarn add crypto-js
  1. utils文件夹放入项目 (最好是放在router目录下 ) 中,在router的初始化文件中,引入utils/query.jsstringifyQueryparseQuery方法,在new VueRouter是时候传递参数,

  2. 修改utils/encryption.js中的baseCryptoCode设置每个项目唯一的值

例:(参考index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from "vue"
import VueRouter from "vue-router";
import { stringifyQuery, parseQuery } from "./utils/query";

Vue.use(VueRouter);

const routes = [];

const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
stringifyQuery: stringifyQuery, // 序列化query参数
parseQuery: parseQuery, // 反序列化query参数
routes
});

export default router

结构

  • utils/encryption.js

    文件提供加密和解密算法(默认在index.html中已经引入了crypto-js.js)

    • getEncrypt 加密 对应的解密方法(getDecrypt)
    • getEncryptToBase64 加密后转base64 对应的解密方法(getDecryptByBase64)
    • getDecrypt 解密 对应的加密方法(getEncrypt)
    • getDecryptByBase64 对base64数据解密 先解析base64,在做解密 对应的加密方法(getEncryptToBase64)
  • utils/query.js

    文件提供了序列化和反序列化的方法

    • stringifyQuery 序列化对象并 加密
    • parseQuery 解密 反序列化对象

原理

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

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

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

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

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

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

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

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

  • 序列化

    vue-router在执行createRoute的时候,获取fullPath会执行getFullPath方法

    createRouter 方法 会获取在 new VueRouter的时候传递的stringifyQuery方法,如果没有这个方法,就会在getFullPath的时候,使用默认的方法

    源码位置:“/vue-router/src/utils/route.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
    export function createRoute (
    record: ?RouteRecord,
    location: Location,
    redirectedFrom?: ?Location,
    router?: VueRouter
    ): Route {
    const stringifyQuery = router && router.options.stringifyQuery

    let query: any = location.query || {}
    try {
    query = clone(query)
    } catch (e) {}

    const route: Route = {
    name: location.name || (record && record.name),
    meta: (record && record.meta) || {},
    path: location.path || '/',
    hash: location.hash || '',
    query,
    params: location.params || {},
    fullPath: getFullPath(location, stringifyQuery),
    matched: record ? formatMatch(record) : []
    }
    if (redirectedFrom) {
    route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery)
    }
    return Object.freeze(route)
    }

    getFullPath 方法接收两个参数(路由对象, 序列化query的方法) 源码:

    1
    2
    3
    4
    5
    6
    7
    function getFullPath (
    { path, query = {}, hash = '' },
    _stringifyQuery
    ): string {
    const stringify = _stringifyQuery || stringifyQuery
    return (path || '/') + stringify(query) + hash
    }
  • 反序列化

    在调用push的时候,会执行this.router.match方法,match方法会执行normalizeLocation

    normalizeLocation通过resolveQuery方法解析path中的query,传入的三个参数(path中的?之后的参数数据字符串,使用push或replace方法传递的query参数,反序列化参数的方法)

    反序列化方法会通过router && router.options.parseQuery获取,如果在new VueRouter的时候传递了parseQuery方法,就是用该方法,如果没有就在resolveQuery方法中使用默认的方法

    源码地址:“/vue-router/src/utils/location.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
    export function normalizeLocation (
    raw: RawLocation,
    current: ?Route,
    append: ?boolean,
    router: ?VueRouter
    ): Location {
    let next: Location = typeof raw === 'string' ? { path: raw } : raw
    // named target
    if (next._normalized) {
    return next
    } else if (next.name) {
    next = extend({}, raw)
    const params = next.params
    if (params && typeof params === 'object') {
    next.params = extend({}, params)
    }
    return next
    }

    // relative params
    if (!next.path && next.params && current) {
    next = extend({}, next)
    next._normalized = true
    const params: any = extend(extend({}, current.params), next.params)
    if (current.name) {
    next.name = current.name
    next.params = params
    } else if (current.matched.length) {
    const rawPath = current.matched[current.matched.length - 1].path
    next.path = fillParams(rawPath, params, `path ${current.path}`)
    } else if (process.env.NODE_ENV !== 'production') {
    warn(false, `relative params navigation requires a current route.`)
    }
    return next
    }

    const parsedPath = parsePath(next.path || '')
    const basePath = (current && current.path) || '/'
    const path = parsedPath.path
    ? resolvePath(parsedPath.path, basePath, append || next.append)
    : basePath

    const query = resolveQuery(
    parsedPath.query,
    next.query,
    router && router.options.parseQuery
    )

    let hash = next.hash || parsedPath.hash
    if (hash && hash.charAt(0) !== '#') {
    hash = `#${hash}`
    }

    return {
    _normalized: true,
    path,
    query,
    hash
    }
    }