我正在研究索引引擎,特别是Apache Lucene Solr。我们愿意将它用于我们的搜索,但我们的框架搜索解决的问题之一是行级访问。
Solr不提供开箱即用的记录访问权限:
< ...> Solr不关心文档级别或通信级别的安全性。
在关于文档级安全性的部分中:http://wiki.apache.org/solr/SolrSecurity#Document_Level_Security
有一些建议 - 使用Manifold CF(高度无证,似乎处于非β前期阶段)或编写自己的请求处理程序/搜索组件(该部分标记为存根) - 我想是后来的一个人会对绩效产生更大的影响。
所以我假设在这个领域没有做太多。
在最近发布的4.0版Solr中,他们引入了两个索引实体。加入似乎是个好主意,因为我们的框架也会联系以了解该记录是否可供用户访问。这里的问题是,有时我们做一个内连接,有时和外连接(取决于乐观(允许禁止的一切)或悲观(一切都被禁止,只有明确允许的)安全设置在范围内)。
为了更好地理解我们的结构:
文档
DocumentNr | Name
------------------
1 | Foo
2 | Bar
DocumentRecordAccess
DocumentNr | UserNr | AllowRead | AllowUpdate | AllowDelete
------------------------------------------------------------
1 | 1 | 1 | 1 | 0
因此,例如,在悲观安全设置中生成的文档查询将是:
SELECT * FROM Documents AS d
INNER JOIN DocumentRecordAccess AS dra ON dra.DocumentNr=d.DocumentNr AND dra.AllowRead=1 AND dra.UserNr=1
这只会返回foo,而不是bar。在乐观的环境中:
SELECT * FROM Documents AS d
LEFT JOIN DocumentRecordAccess AS dra ON dra.DocumentNr=d.DocumentNr AND dra.AllowRead=1 AND dra.UserNr=1
返回两者 - Foo和Bar。
回到我的问题 - 也许有人已经这样做了,可以分享他们的见解和经验吗?
答案 0 :(得分:7)
恐怕这里没有简单的解决方案。您将不得不牺牲一些东西来使ACL与搜索一起工作。
如果你的语料库大小很小(我说最多10K文档),你可以创建一个禁止(或允许,不管那么详细)文档的缓存位集并发送相关的过滤查询{{1} }。不用说,这不会扩展。发送大型查询会使搜索速度变慢,但这是可管理的(当然是一个点)。查询解析is cheap。
如果您能够以某种方式对这些文档进行分组并在文档组上应用ACL,这将允许缩短查询长度,并且上述方法将完全适合。这几乎就是我们正在使用的 - 我们的解决方案实现了分类,并通过(+*:* -DocumentNr:1 ... -DocumentNr:X)
查询完成了分类权限。
如果您不需要显示整体结果集计数,则可以运行查询并在客户端过滤结果集。再次,不完美。
您还可以对数据结构进行非规范化,并将这两个表格平铺在单个文档中,如下所示:
DocumentNr:1
姓名:Foo
Allowed_users:u1,u2,u3(或Forbidden_users:...)
其余的就像使用您的查询发送用户ID一样简单。
如果ACL很少改变和,那么只有当他们能够重新索引整个语料库时,才能生效。
您可以编写一个自定义查询过滤器,该过滤器将从数据库中检索的用户(组?)缓存fq
个允许或禁止的文档。这不仅需要为Solr webapp提供数据库访问,还需要扩展/重新打包Solr附带的.war。虽然这相对容易,但harder part would be cache invalidation:主应用程序应该在ACL数据发生变化时以某种方式向Solr应用程序发出信号。
如果您可以将Solr和您的应用程序放在同一个JVM上并使用javabin驱动程序,则选项1和2可能更合理。
如果不了解语料库/ ACL的具体细节,很难提出更多建议。
答案 1 :(得分:3)
我同意mindas,他建议的内容(sol-4),我已经以同样的方式实现了我的解决方案,但区别在于我有几种不同类型的ACL。在用户组级别,用户级别甚至文档级别(私人访问)。
解决方案工作正常。但在我的情况下,主要关注的是ACL经常更改并且需要在索引中更新,这意味着搜索性能也不会受到影响。
我正在尝试通过负载平衡和向集群添加更多节点来管理它。
mindas,unicron你可以把你的想法放在这个吗?