Java 这是允许用户进行通配符搜索的正确方法吗?

Java 这是允许用户进行通配符搜索的正确方法吗?,java,sql,security,wildcard,parameterized-query,Java,Sql,Security,Wildcard,Parameterized Query,例如,给定一个文本框名称,用户需求希望能够进行通配符搜索(例如包含、以开头、以结尾) 只要我还在后端(Java)中使用参数化查询,接受sql通配符(“%”和“"”)作为输入可以吗?实际上,允许用户构建自己的正则表达式,这正是用户需求的全部内容 例如: 中的用户类型 textbox = '%are%' 此参数被馈送到后端,如下所示: public class PersonDaoImpl { public List<Person> search(String nam

例如,给定一个文本框名称,用户需求希望能够进行通配符搜索(例如包含、以开头、以结尾)

只要我还在后端(Java)中使用参数化查询,接受sql通配符(“%”和“"”)作为输入可以吗?实际上,允许用户构建自己的正则表达式,这正是用户需求的全部内容

例如:

  • 中的用户类型

    textbox = '%are%'
    
  • 此参数被馈送到后端,如下所示:

    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();
            } 
    }  
    
    公共类persondaimpl{
    公共列表搜索(字符串名称){//name从带有sql通配符的文本框中获取值
    Query q=mgr.createNativeQuery('select*from Person where name like:name');//默认为始终使用like,因为需要带有sql通配符的搜索键
    q、 setParameter('name',name);//提供来自屏幕的输入
    返回q.getResultList();
    } 
    }  
    
  • 由于用户提供了一个正则表达式,所以结果集将包括名为“Waren”、“Jared”、“Clare”、“Blare”的人员
  • 使用SQL参数化查询,我可以确保不允许SQL注入。这实现了通配符搜索的用户需求,但它是否违反了我可能遗漏的任何内容

    更新:
    刚刚发现Google也允许通配符,这与用户需要知道(或被告知)如何构造SQL“LIKE”语法的事实相违背,但仅此而已。您可能会以这种方式结束一个缓慢的查询,因为它通常无法使用索引,但我不会担心安全性或正确性。

    它是“安全的”,但可能不是一个好主意,原因有二:

  • 要求用户了解sql语法可能不是最好的ui设计
  • 这对性能很糟糕:这些查询通常无法使用索引,因此执行起来很慢。它们需要大量的cpu时间来比较所有这些文本,因此它们会给服务器增加大量负载(与已经很高的执行时间不成比例)。您需要一个依赖全文索引的解决方案
  • 我很好奇,
    name
    参数是如何在请求中设置的?这是什么站台?(OP missed
    setParameter
    之前)

    正如您所指出的,用户需要知道通配符语法,即使用
    %
    \uu
    等。更流行的方法是只从用户名中获取字符串,并提供“精确匹配”/“开始于”/“名称中的任意位置”选项。如果您采用这种方式,那么在前两种情况下,您也将能够执行更高效的查询

    编辑:

    如果客户坚持使用
    contains
    query,那么我认为您当前要求最终用户输入模式的方法比将
    %
    放在输入字符串周围将其转换为模式更好

    这是因为用户仍然可以选择不将
    %
    添加(或有选择地添加)到搜索字符串,从而加快查询执行。例如:

    • 如果用户输入搜索字符串
      Don
      ,则查询为
      select。。。从…起其中的名称类似于“Don”
      。RDBMS最有可能在名称上使用索引

    • 如果用户输入搜索字符串
      Don%
      则查询为
      select。。。从…起其中的名称类似于“Don%”
      。RDBMS仍然很可能使用名称索引

    • 如果用户输入搜索字符串
      %Don
      %Don%
      ,则无法使用索引


    我不确定:名称将如何在sql中解释。您可能必须像下面这样编写“从姓名为'+'\''+名称为+'\''的人员中选择*”。我建议用户应该通过%are%而不是''%are%',因为您始终需要引号,您可以编写该部分的代码…编辑我的问题并添加缺少的代码行,q.setParameter('name',name),它将用变量名的值替换查询中的:name。在no.2上,客户端需要一个实际为“%searchkey%”的“contains”搜索。我已经通知了客户由于这一点,它的性能已被考虑和功能超过性能。我确实计划添加一些索引,如回答/问题中所述。@Carlos-你没有抓住要点。Sql Server有一个名为CONTAINS()的函数,它可以完全满足客户机的要求,而不会造成性能损失。很好,我不知道这个函数。我正在使用Sybase,将尝试查看它是否有类似的功能。我想如果用户想要“开始于”和“结束于”,那么如果存在这样的现有函数,那么它将是对startsWith或endsWith的函数调用?感谢您对安全性或正确性的评论。此外,我一直在思考Jira Issue Navigator如何通过允许用户提供表达式来允许高级搜索。但当然,我使用的这个通配符搜索没有JIRA高级搜索那么灵活/复杂;我对问题进行了编辑以反映这一点,感谢您的关注。这是在Java中,它在下面使用PreparedStatements进行参数化查询,其中:name可以通过执行我刚才添加的代码行替换为值。确定:)查看此处的其他注释,如果客户总是希望“包含”查询,那么您不妨将
    %
    放在输入周围。另一方面,允许用户输入它允许用户输入
    term
    term%
    %term
    %term%
    ,这可以加快查询执行速度。是的,我希望允许用户能够构建正则表达式,他/她甚至可以执行类似于“%ap%zel”的操作来获得“rapanzel”。:)