【问题标题】:Retrieving matched context of MySQL fulltext search in PHP (and security)在 PHP(和安全性)中检索 MySQL 全文搜索的匹配上下文
【发布时间】:2011-07-08 11:44:12
【问题描述】:

我正在对我的 MySQL 表“页面”进行全文搜索。我正在显示与“标题”(纯文本,VARCHAR,255)或“内容”(html,TEXT)中的关键字匹配的页面列表。在“内容”字段中找到匹配项时,我想显示找到匹配项的 sn-p。我不知道该怎么做。

你能告诉我正确的方向吗?

$query = '  SELECT 
                *, 
                MATCH(title, content) AGAINST("'.$keyword.'") AS score 
            FROM 
                page 
            WHERE 
                MATCH(title, content) AGAINST("'.$keyword.'")
            ORDER BY 
                score 
            DESC    ';
$result = mysql_query($query) or die (mysql_error());
if(mysql_num_rows($result) > 0) {   
    $output .= '<p>Your keyword matches the following pages:</p>';
    while($row = mysql_fetch_assoc($result)){

        $title      = htmlentities($row['title']);
        $content    = htmlentities(strip_tags($row['content']));
        $content    = limit_text($content, 250); // Cuts it down to 250 characters plus ...

        $output .= '<h2>'.$title.'</h2>';
        if(trim($content) != '') {
            $output .= '<p>'.$content.'</p>'; // I'd like to place a snippet here with the matched context
        }           
    }   
} else {
    $output .= '<p>Keyword not found...</p>';       
}

另外,我有一个关于安全的问题。现在我正在通过三种方式检查$keyword

  • 不是空白?
  • 超过 2 个字符?
  • 不危险? (见下文)

我用正则表达式匹配下面的,看看用户输入是否危险

<script|&lt;script|&gt;script|document.|alert|bcc:|cc:|x-mailer:|to:|recipient|truncate|drop table

这可能有点荒谬且易于解决,但它至少是针对 XSS 攻击的最低限度的保护形式。安全过滤用于搜索的关键字的推荐方法是什么? PHPIDS 是不是矫枉过正?

【问题讨论】:

  • 在回答您问题的安全部分时,请尽可能使用PDO。否则,您至少应该运行 $keywordmysql_real_escape_string()
  • 您的 xss 保护很弱。也可以肯定地说 drop table 不能永远攻击此代码,因为 mysql_query() 不允许查询堆叠。
  • @itchy 谢谢,我会调查PDO,但现在我只使用mysql_real_escape_string(),谢谢。 @Rook,感谢您的见解,我意识到这一点,这就是我正在寻找替代方案的原因。

标签: mysql security search full-text-search


【解决方案1】:

这应该让您开始“上下文”部分...

// return the part of the content where the keyword was matched
function get_surrounding_text($keyword, $content, $padding)
{
    $position = strpos($content, $keyword);
    // starting at (where keyword was found - padding), retrieve
    // (padding + keyword length + padding) characters from the content
    $snippet = substr($content, $position - $padding, (strlen($keyword) + $padding * 2));
    return '...' . $snippet . '...';
}

$content = 'this is a really long string of characters with a magic word buried somewhere in it';
$keyword = 'magic';
echo get_surrounding_text($keyword, $content, 15); // echoes '... string with a magic word in it...'

此函数不考虑填充边界超出内容字符串的情况,例如在内容的开头或结尾附近找到关键字时。它也不考虑多个匹配项等。但希望它至少可以为您指明正确的方向。

【讨论】:

    【解决方案2】:

    如果我是你,我可能会先将 $keyword 用于函数清理它。并且作为记录,您最好将 $keyword 中的所有单词放入数组中,以便您可以在必要时使用boolean search。(例如在每个单词前面加上 + 以获得 AND 效果)

    【讨论】:

      【解决方案3】:

      与其尝试自己过滤 $keywords 变量,您可以简单地使用 prepared statement 而不必担心错过潜在的漏洞利用:

      <?php
      $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
      $stmt->bindParam(':name', $name);
      $stmt->bindParam(':value', $value);
      
      // insert one row
      $name = 'one';
      $value = 1;
      $stmt->execute();
      
      // insert another row with different values
      $name = 'two';
      $value = 2;
      $stmt->execute();
      ?>
      

      【讨论】:

      猜你喜欢
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-22
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-24
      相关资源
      最近更新 更多