我需要让我的用户在搜索中使用星号 (*) 作为通配符。
将星号转换为 % 并在 sql 查询中使用 LIKE 是否安全。
我知道用户正则表达式可能会导致需要永远计算的常规 epressions。我认为在这种情况下我不可能,但是这样做是否还有其他安全问题?
表达式中的通配符like
会导致查询执行发生变化,从而使 RDBMS 使用全表扫描而不是使用索引。当有大量数据时,这可能会减慢查询速度。我建议检查用户输入的第一个星号前是否存在至少一些非通配符。
另请注意,如果您转换*
为%
, 并使用LIKE
,您也需要注意_
,否则它将匹配任何单个字符,而不仅仅是下划线。
真正的问题是,让用户决定部分查询是否安全。
即使在简单的情况下,向数据库提供用户数据也是不安全的。
允许用户输入直接提供给数据库可能是危险的,但就您的过滤器和使用数据库转义策略而言(即:(mysql_real_escape_string()
准备充分的语句或任何 ORM 将为您执行此操作)应该足够安全。
但是,它可能会导致性能问题,一个简单EXPLAIN
的查询应该会警告您 RDBMS 引擎扫描了多少行。
实现此类功能的最佳方法是使用搜索引擎。(这不是你想要做的吗?)
有很多选择可以帮助您实现这一点。
你可以看看 Sphinx、Solr、Xapian 甚至 Lucene。都有很好的选择。
它们基本上允许您“索引”您的内容以进行全文搜索,同时提高性能。
它们还可以提供一些令人难以置信的功能,例如OR
、AND
、LIKE
、MINUS
等。比较器/运算符。
然后您可能会对这个问题感兴趣:选择一个独立的全文搜索服务器:Sphinx 还是 SOLR?
如果您所做的只是像这样的简单替换
str_replace('*','%',$query)
那么我没有预见到任何安全问题,我相信这是您所关心的。你不会打开任何 SQL 注入的可能性或任何东西(至少不会通过这种替换,如果你不逃避输入,你可能仍然有安全问题)。
但是,正如其他一些用户指出的那样,您将打开一些性能问题。如果我搜索 just 会发生什么*
,我会拿回你的整个桌子吗?最好的方法(如果你不想使用数据库搜索引擎)是做一些用户验证。如果您想防止对查询进行全表扫描,最有可能的是,您需要限制用户只使用前导通配符或尾随通配符。
好的:
*foo
bar*
不太好:
*foo*
ba*r
这实际上取决于您拥有多少行以及您对用户提供实际输入的信任程度。