2011-03-04 87 views
6

我在我的MySQL表「頁面」上進行全文搜索。我在其「標題」(純文本,VARCHAR,255)或「內容」(html,TEXT)中顯示與關鍵字匹配的頁面列表。當在「內容」字段中找到匹配項時,我想顯示找到匹配項的片段。我不知道如何去做這件事。在PHP(和安全)中檢索MySQL全文搜索的匹配上下文

你能幫我正確的方向嗎?

$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矯枉過正?

+0

爲了迴應您的問題的安全性部分,請儘可能使用[PDO](http://php.net/manual/en/ref.pdo-mysql.php)。否則,你應該至少通過'mysql_real_escape_string()'運行'$ keyword'。 – glomad 2011-03-04 01:07:50

+0

您的xss保護功能很弱。另外它可以安全地說'drop table'可以**永遠不會**攻擊這個代碼,因爲'mysql_query()'不允許查詢堆棧。 – rook 2011-03-04 03:23:53

+0

@itchy謝謝,我將研究'PDO',但現在我只使用'mysql_real_escape_string()',謝謝。 @Rook,感謝您的見解,我意識到這一點,這就是爲什麼我要尋找替代品。 – maartenmachiels 2011-03-04 10:16:15

回答

6

這應該讓你開始「上下文「部分...

// 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

,而不是試圖自己過濾$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(); 
?> 
+0

感謝您對此...我發現了一個很好的教程http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/,它會讓我從PDO開始。 – maartenmachiels 2011-03-04 10:31:32

0

我可能會得到$關鍵字功能的第一清理如果我是你。並且爲了記錄你最好把所有關鍵字放在$關鍵字中,這樣你可以在必要時使用boolean search(比如在每個單詞的前面加+來獲得AND效果)