23 elasticsearch带权限搜索系统设计 - xiaoxin01/Blog GitHub Wiki

企业内的应用系统,大多都权限设定,人员只能查看其有权限的资料。本文介绍如何将这种带权限的数据,导入到elasticsearch,并实现带权限的搜索

思路

一个带权限搜索系统,包含2个部分:

  • 索引的资料及其权限信息
  • 进行搜索的人员拥有的权限信息

搜索时将这2部分数据进行比对,便可以让搜索的人员仅搜索出其有权限的资料。

如何在elasticsearch搜索的同时,对比权限信息?

在query时,可以用中filter功能来过滤有权限的文档,且不影响搜索结果的排序(_score),详情可以参考Query and filter context

于是可以在每条index的数据中,加入权限字段:

{
    "title" : "trying out Elasticsearch",
    "security_data": true,
    "security_users": ["张三", "李四", "王五"],
    "security_groups": ["hr", "develop", "manager"],
}

在搜索时,加入搜索人员拥有的权限:

{
  "query": {
    "bool": {
      "must":[{
        "query_string": {
          "fields" : ["title^2", "content"],
          "query" : "Elasticsearch",
          "default_operator": "AND"
        }
      }],
      "filter": {
        "bool": {
          "should": [{     
            "terms": {
              "security_groups.keyword": [
                "hr"
              ]
            }
          },
          {
            "terms": {
              "security_users.keyword": [
                "张三"
              ]
            }
          },
          {
            "bool": {
               "must_not": [{
                  "exists": {
                      "field": "security_data"
                  }
                }]
            }
          }]
        }
      }
    }
  }
}

这里最外层使用的是bool query,must段用来做关键字查询,filter段用来做权限匹配。filter段又嵌套了should,表示3个条件只要满足一个即可,最后一个must_not是为了兼容搜索不带权限信息的资料。

如何索引带权限的资料?

以logstash抓取db资料为例,首先db中生成如下格式的资料:

id title content security_users security_groups modified deleted
1 data1 content 1 user1,user2, group1,group2 2019/6/14 false
2 data2 content 2 user3,user4, group3,group4 2019/6/12 false
3 data3 content 3 user5,user6, group5,group6 2019/6/13 false

然后配置logstash的config,添加security_data字段,并将security_users和security_groups转换为array。

modified栏位主要用于增量抓取数据,避免每次logstash启动时扫描全表。

input {
    jdbc {
        jdbc_driver_library => "/usr/share/java/mssql-jdbc-7.0.0.jre8.jar"
        jdbc_driver_class => "com.microsoft.sqlserver.jdbc.SQLServerDriver"
        jdbc_connection_string => "${JDBC_CONNECTION_STRING}"
        jdbc_user => "${JDBC_USER}"
        jdbc_password => "${JDBC_PASSWORD}"
        schedule => "0 1 * * *"
        jdbc_default_timezone => "Asia/Shanghai"
        statement => "${JDBC_STATEMENT}"
        use_column_value => true
        tracking_column => "modified"
        tracking_column_type => "timestamp"
        jdbc_fetch_size => 2000        
        last_run_metadata_path => "/usr/share/logstash/state/state"
    }
}
filter {
  mutate {
    add_field => {
      "security_data" => "true"
    }
    convert => {
      "deleted" => "boolean"
    }
  }
  mutate {
    split => {
        "security_users" => ","
        "security_groups" => ","
    }
  }
  mutate { uppercase => [ "users_id", "groups_id" ] }
}
output {
    elasticsearch {
        index => "${ELASTICSEARCH_INDEX}"
        document_id => "%{id}"
        hosts => "${ELASTICSEARCH_HOSTS}"
        user => "${ELASTICSEARCH_USER}"
        password => "${ELASTICSEARCH_PASSWORD}"
    }
}

如何获取人员的权限信息?

可以单独搭建一个Groupserver,同步不同系统的用户组织信息,并提供api用于获取用户所属组织。

传送门:待续

参考

⚠️ **GitHub.com Fallback** ⚠️