Vue实现前端标签绑定搜索

前言

  • 在开发Metasploit前端时需要实现一个搜索payload的功能,由于是通过rpc服务获取当前exploit可用的payload,这是在内存里的元数据获取的数据,所以并没有像数据库这样有过滤功能,就有了使用前端实现标签搜索。

实现思路

  • 首先把payload的全称按照/分词生成标签,例如:windows/meterpreter/reverse_tcp分割后变成windowsmeterpreterreverse_tcp三个标签,按照这种方法将所有的payload分成标签,然后去重。
async compatible_payloads(fullname) {
  await module_compatible_payloads(fullname).then(response => {
    this.payloads_all = response.result.payloads
  })
},
  • 先获取当前exploit可用payload,存放在payloads_all,然后监听payloads_all的变化,拷贝一份用于过滤操作,存放在payloads_filter,当payloads_filter变化时生成分词标签,将标签去重后存放在payloads_tags_all,当payloads_tags_all变化后再拷贝一份用于过滤操作,可能有点绕。
watch: {
  // 拷贝一份用于过滤
  payloads_all: function() {
    this.payloads_filter = this.payloads_all
  },
  // 拷贝一份用于过滤
  payloads_tags_all: function() {
    this.payloads_tags_filter = this.payloads_tags_all
  },
  payloads_filter: function() {
    var tags = []
    this.payloads_filter.forEach(payload_line => {
      // 生成payload标签
      tags.push(...payload_line.split('/'))
    })
    this.payloads_tags_all = Array.from(new Set(tags))
  }
},

payload标签搜索

  • 在element的选择器中定义下面属性,远程方法为load_tags
<el-select
  v-if="activeStep==1"
  v-model="payload.tags"
  default-first-option
  clearable
  multiple
  filterable
  remote
  style="width: 350px"
  placeholder="tags"
  :remote-method="load_tags"
  :loading="tags_loading"
  @change="select_payload_tags"
>
  <el-option
    v-for="(p,index) in payloads_tags_filter"
    :key="index"
    :label="p"
    :value="p"
  />
</el-select>
  • 下面的是load_tags的方法,和一般过滤一样,没什么特别的,判断过滤的关键词不为空就过滤,关键词为空就将之前保存的payloads_tags_all覆盖掉payloads_tags_filter
load_tags(query) {
  if (query !== '') {
    this.tags_loading = true
    this.payloads_tags_filter = this.payloads_tags_all.filter(p => {
      return p.toLowerCase().indexOf(query.toLowerCase()) > -1
    })
    this.tags_loading = false
  } else {
    this.payloads_tags_filter = this.payloads_tags_all
  }
},
  • 这个方法最后改变了payloads_tags_filter,将payload标签可选范围缩小了。
select_payload_tags() {
  this.load_payload('')
},
  • 最后点击标签触发payload搜索load_payload方法。

payload搜索

  • 在element的选择器中定义下面属性,远程方法为load_payload
<el-select
  v-model="payload.fullname"
  default-first-option
  clearable
  filterable
  remote
  reserve-keyword
  style="width: 350px"
  placeholder="fullname"
  :remote-method="load_payload"
  :loading="select_loading"
>
  <el-option
    v-for="(p,index) in payloads_filter"
    :key="index"
    :label="p"
    :value="p"
  />
</el-select>
  • 下面应该就是核心代码了
load_payload(query) {
  // 搜索payload标签
  if (query !== '' || this.payload.tags.length) {
    this.select_loading = true
    this.payloads_filter = this.payloads_all.filter(p => {
      var is_include = (intersection(compact(p.split('/')), compact(this.payload.tags)).length === this.payload.tags.length)
      if (!is_include) {
        return false
      } else if (query !== '') {
        return p.toLowerCase().indexOf(query.toLowerCase()) > -1
      } else {
        return true
      }
    })
    this.select_loading = false
  } else {
    this.payloads_filter = this.payloads_all
  }
},
  • 有两个地方触发了load_payload方法,第一个在payload搜索时触发,会传关键词搜索;第二个在选择标签后改变payload.tags数组后触发,会传一个空字符串搜索,先判断关键词是否为空,或者payload.tags数组的长度是否大于0,有一个为真就加锁进入过滤操作,下面讲一下搜索过滤的思路。

搜索过滤

  • 因为我们payload.tags是一个数组集合,这不用每一个标签都去判断是否在payload的全称里,有一个非常简单的方法,先将payload的全称分割得到标签,再和payload.tags做集合求并集操作,得到并集后和payload.tags作比较,如果是一样就表明payload全称里有payload.tags里的标签,而且是准确的。
posted @ 2020-05-25 16:13  三米前有蕉皮  阅读(203)  评论(0编辑  收藏