浏览器地址栏URL防篡改攻略

举报
SHQ5785 发表于 2024/06/27 09:21:34 2024/06/27
【摘要】 一、前言在应用 vue.js 开发前端项目时,浏览器中url 地址栏参数的处理是一个很基础但却很重要的问题。在很多情况下,我们需要从 url 中获取参数,比如从上一个页面跳转到当前页面,需要将一些信息传递给这个页面,这时候就需要将这些信息以参数的形式传递给 url。但是,有时候这些参数又需要被隐藏起来,毕竟 url 中敏感信息不应该被轻易泄露,因此本文将介绍如何在 vue.js 中隐藏地址...

一、前言

在应用 vue.js 开发前端项目时,浏览器中url 地址栏参数的处理是一个很基础但却很重要的问题。在很多情况下,我们需要从 url 中获取参数,比如从上一个页面跳转到当前页面,需要将一些信息传递给这个页面,这时候就需要将这些信息以参数的形式传递给 url。但是,有时候这些参数又需要被隐藏起来,毕竟 url 中敏感信息不应该被轻易泄露,因此本文将介绍如何在 vue.js 中隐藏地址栏参数。

二、动态路由

首先,我们可以通过 Vue.js 的动态路由来隐藏地址栏中的参数。动态路由是一种将 URL 中的参数与实际展示的组件进行映射的技术。举个例子,我们假设有一个文章列表页,每篇文章都有一个唯一的 ID 用于标识这篇文章,我们可以将这个 ID 作为路由的一个参数,然后在组件中读取这个 ID 并使用它来获取对应的文章信息。

具体来说,我们可以首先在路由配置中定义一条动态路由,将路由的路径中的某一段(比如文章 ID)设置为动态参数:

const router = new VueRouter({
  routes: [
    {
      path: '/article/:id',
      name: 'Article',
      component: Article
    }
  ]
})

在这个例子中,:id 就是一个动态参数,表示文章的 ID。在对应的组件中,我们可以通过 $route.params.id 来获取这个参数的值:

export default {
  mounted () {
    console.log(this.$route.params.id)
  }
}

这样,在用户访问这个路由时,即可在组件中获取到参数的值,而 URL 中并不会显示这个参数。

三、Params 参数

除了使用动态路由,我们还可以通过 Params 参数来隐藏地址栏中的参数。

举个例子,我们假设有一个搜索页,需要在搜索时将用户输入的关键词传递给服务器来获取匹配的结果,可以将输入的关键词作为 Params 参数,然后在路由组件中获取和解析这个参数:

const router = new VueRouter({
  routes: [
    {
      path: '/search',
      name: 'Search',
      component: Search
    }
  ]
})

// 当用户在输入框中输入搜索关键词时
this.$router.push({
  name: 'Search',
  params: { keyword: '关键词' }
})

export default {
  mounted () {
    console.log(this.$route.params.keyword)
  }
}

在这个例子中,params 选项表示传递的参数。然后在组件中可以通过 $route.params.keyword 来获取这个参数的值。这样在 URL 中就看不到实际传递的参数了。

四、在 URL 中使用加密参数

除了以上两种方法,我们还可以在 URL 中使用加密参数来隐藏地址栏参数。具体来说,我们可以将参数进行加密后再传递给 URL,这样在 URL 中即使被他人截获,也无法轻易解析出实际的参数值。

加密的方式有很多种,可以使用对称加密(如 DESAES)或非对称加密(如 RSA)等算法来进行加密。在这里不做过多介绍。

在 Vue.js 中使用加密参数时,可以将加密后的参数写入 CookieLocalStorage 等本地存储器中,然后让后续的页面读取这个数据并进行解密。这样可以保证加密的参数只在本地存储器中显示,而不会暴露给 URL。唯一需要注意的是加密后的参数长度应该要比明文参数的长度要小,不然会导致 Cookie 等存储器过大。

五、参数转码

应用Base64实现将URL参数转码并作为参数追加至url中,若同一用户拷贝该url至新视图并试图修改url参数,则无法继续访问页面,或者不同用户拷贝该url不做任何url修改在新视图中也无法正常访问,因为url中涉及用户身份标识。

注意⚠️:应用Base64进行转码后得到的结果不定长,存在转码结果过长导致请求失败或数据丢失风险。建议使用哈希算法,例如MD5SHA-256,详参博文《Vue进阶(贰零捌)六种常用数据加密方式》。

import Base64 from 'base-64'

Vue.prototype.$setCCMSAuthCode = function (obj) {
  let copyQuery = JSON.parse(JSON.stringify((obj.query)))
  copyQuery.usrUid = store.getters.usrUid
  return Base64.encode(encodeURIComponent(JSON.stringify(copyQuery)))
}

Vue.prototype.$router_push = function (obj) {
  if (obj.query && JSON.stringify(obj.query) !== '{}') {
    let copyQuery = JSON.parse(JSON.stringify((obj.query)))
    copyQuery.usrUid = store.getters.usrUid
    obj.query.AuthCode = Base64.encode(encodeURIComponent(JSON.stringify(copyQuery)))
    this.$router.push({
      path: obj.path,
      query: obj.query
    })
  } else {
    this.$router.push({
      path: obj.path
    })
  }
}

// 白名单的路径
// const whiteList = ['/login']// 不重定向白名单
let islogin = false
router.beforeEach((to, from, next) => {
  NProgress.start()
  if (islogin) {
    islogin = false
    next()
    NProgress.done() // 在hash模式下 改变手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行!
    return
  }
// 未登录
  if (!store.getters.usrUid) {
    store.dispatch('GetInfo').then(res => {
      if (res.code === 99) {
        islogin = true
        if (process.env.NODE_ENV === 'development') {
          next('/login')
        } else {
          window.location.href = window.logOutUrl
        }
        return
      }
      const role = res.usrUid
      store.dispatch('SetRole', role)
      router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
      next(to.fullPath) // hack方法 确保addRoutes已完成
    })
  } else {
    // 方案一
    if (to.fullPath !== '/login' && JSON.stringify(to.query) !== '{}') {
      if (to.fullPath.indexOf('AuthCode') < 0) {
        let copyQuery = JSON.parse(JSON.stringify((to.query)))
        copyQuery.usrUid = store.getters.usrUid
        let obj = {AuthCode: Base64.encode(encodeURIComponent(JSON.stringify(copyQuery)))}
        let query = Object.assign({}, to.query, obj)
        console.log(query, 'query')
        router.push({path: to.path, query: query})
        return
      } else {
        let copyQuery = JSON.parse(JSON.stringify((to.query)))
        copyQuery.usrUid = store.getters.usrUid
        delete copyQuery.AuthCode
        if (decodeURIComponent(Base64.decode(to.query.CCMS_AuthCode)) !== JSON.stringify(copyQuery)) {
          next('/404')
        }
      }
    }
    // 方案二
    // if (to.fullPath !== '/login' && JSON.stringify(to.query) !== '{}') {
    //   let copyQuery = JSON.parse(JSON.stringify((to.query)))
    //   copyQuery.usrUid = store.getters.usrUid
    //   delete copyQuery.AuthCode
    //   if (!to.query.AuthCode || decodeURIComponent(Base64.decode(to.query.AuthCode)) !== JSON.stringify(copyQuery)) {
    //     next('/404')
    //   }
    // }
    if (to.path === '/login') {
      next()
    } else {
      next()
      NProgress.done() // 在hash模式下 改变手动改变hash 重定向回来 不会触发afterEach 暂时hack方案 ps:history模式下无问题,可删除该行!
    }
  }
})
router.afterEach((to) => {

  NProgress.done()
  // 跳转回页面顶部
  window.scrollTo(0, 0)
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  i18n,
  components: {App},
  template: '<App/>'
})

六、综述

以上就是在 Vue.js 中浏览器地址栏URL防篡改的若干种方法。无论哪种方法,都需要确保在保证安全性的前提下,尽可能的隐藏 URL 中的参数值。诚然,这并不是一件简单的事情,但在实际开发中,对于一些敏感数据而言,这个问题却是非常重要的。

七、拓展阅读

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。