23 elasticsearch带权限搜索系统设计 - xiaoxin01/Blog GitHub Wiki
企业内的应用系统,大多都权限设定,人员只能查看其有权限的资料。本文介绍如何将这种带权限的数据,导入到elasticsearch,并实现带权限的搜索
一个带权限搜索系统,包含2个部分:
- 索引的资料及其权限信息
- 进行搜索的人员拥有的权限信息
搜索时将这2部分数据进行比对,便可以让搜索的人员仅搜索出其有权限的资料。
在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用于获取用户所属组织。
传送门:待续