这是允许通配符搜索用户的正确方法吗?
例如,给定一个文本框名称,用户要求能够进行通配符搜索(例如包含、开头为、结尾为)。
只要我仍在后端(Java)中使用参数化查询,是否可以接受 sql 通配符(“%”和“_”)作为输入?实际上,允许用户构建自己的正则表达式,这就是用户的需求。
示例:
用户在
中键入文本框 = '%are%'
中输入此参数,如下所示:
公共类 PersonDaoImpl { 公开列表<人员> search(String name){//name 从带有 sql 通配符的文本框中获取值 Query q = mgr.createNativeQuery('select * from Person where name like :name'); //默认总是使用like,因为需要带有sql通配符的searchkey q.setParameter('name', name);//给出来自屏幕的输入 返回 q.getResultList(); } }
- 结果集将包括名称为“Waren”、“Jared”、“Clare”、“Blare”的人员,正如预期的那样,因为用户提供了正则表达式。
通过 SQL 参数化查询,我可以确保不会允许 SQL 注入。这实现了通配符搜索的用户要求,但也许它违反了我可能错过的任何内容?
更新: 刚刚发现 Google 也允许通配符,来自他们的 帮助页面。
Given a textbox name for example, the user requirement wants to be able to do a wildcard search (such as contains, starts with, ends with).
Is it ok to accept the sql wildcard characters ('%' and '_') as input as long as I am still using parameterized query in the backend (Java)? Effectively, allowing the user to build his own regular expression which is what the user's requirement is all about.
Example:
User types in the
textbox = '%are%'
This parameter is feed to the backend as such:
public class PersonDaoImpl { public List<Person> search(String name){//name gets the value from textbox w/ sql wildcards Query q = mgr.createNativeQuery('select * from Person where name like :name'); //default to always use like since expecting searchkey with sql wildcards q.setParameter('name', name);//gives the input from the screen return q.getResultList(); } }
- The result set would include people with names 'Waren', 'Jared', 'Clare', 'Blare' as expected since user provided a regular expression.
With the SQL Parameterize Query, I can ensure that I won't be allowing SQL Injection. This implements the user requirement for wildcard search, but perhaps does it violate anything that I may have missed?
UPDATES:
Just found out that Google allows wildcard too, from their help page.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,它违反了用户需要知道(或被告知)如何构造 SQL“LIKE”语法的事实,但仅此而已。这样您可能会得到一个缓慢的查询,因为它通常无法使用索引,但我不会担心安全性或正确性。
Well, it violates the fact that the user needs to know (or be told) how to construct SQL "LIKE" syntax, but that's all. You could end up with a slow query this way, in that it won't usually be able to use an index, but I wouldn't be concerned in terms of security or correctness.
它是“安全的”,但可能不是一个好主意,原因有两个:
It's "safe", but probably not a good idea, for two reasons:
我很好奇,(OP 之前错过了name
参数最终如何在请求中设置?这是什么平台?setParameter
)正如您所指出的,用户需要了解通配符语法,即使用
%
、_
等。更流行的方法是仅从用户名中获取字符串,以及“完全匹配”/“开头为”/“名称中的任意位置”选项。如果您走这条路,您还可以在前两种情况下执行更有效的查询。编辑:
如果客户坚持
contains
查询,那么我认为您当前的方法是要求最终用户输入模式,然后通过输入%
将输入字符串转换为模式围绕它。这是因为用户仍然可以选择不添加(或有选择地添加)
%
到搜索字符串,从而加快查询执行速度。例如:如果用户输入搜索字符串
Don
,则查询为select ... from ... where name like 'Don'
。 RDBMS 很可能会使用名称索引。如果用户输入搜索字符串
Don%
,则查询为select ... from ... where name like 'Don%'
。 RDBMS 仍然很可能使用名称索引。如果用户输入搜索字符串
%Don
或%Don%
则无法使用索引。I am curious, how does the(OP missedname
parameter end up getting set in the request? What platform is this?setParameter
earlier)As you noted the user need to know the wild-card syntax i.e. the use of
%
,_
, etc. A more popular approach is to just get the string from the username, along with an option for 'exact match'/'starts-with'/'anywhere-in-name'. If you go that route you will also be able to execute a more efficient query in the first two cases.EDIT:
If the customer insists on
contains
query then I think your current approach of requiring the end-user to input a pattern better then converting the input string to pattern by putting%
around it.This is because the users will still have the option of not adding (or selectively adding) the
%
to the search string, resulting in faster query execution. For example:If the user enter search string
Don
the query isselect ... from ... where name like 'Don'
. The RDBMS will most likely use the index on name.If the user enter search string
Don%
the query isselect ... from ... where name like 'Don%'
. The RDBMS will still quite likely use the index on name.If the user enter search string
%Don
or%Don%
then the index cannot be used.