簡體   English   中英

從樣式中的HTML字符串中剝離所有標記屬性

[英]Stripping all tag attributes from a HTML string except style

我有一個表單,用戶可以使用TinyMCE進行樣式輸入描述。 因此,我的用戶可以插入HTML。 我已經使用strip_tags剝離了幾乎所有HTML元素,但是用戶仍然可以輸入惡意值,例如:

<strong onclick="window.location='http://example.com'">Evil</strong>

我想通過從style除去所有標簽中的所有屬性來阻止用戶執行此操作。

我只能找到去除所有屬性或僅去除指定屬性的解決方案。 我只想保留style屬性。

我已經嘗試了DOMDocument,但似乎自己添加了DOCTYPEhtml標簽,將其輸出為整個HTML文檔。 此外,有時似乎會隨機添加HTML實體,例如上下顛倒的問號。

這是我的DOMDocument實現:

//Example "evil" input
$description = "<p><strong onclick=\"alert('evil');\">Evil</strong></p>";

//Strip all tags from description except these
$description = strip_tags($description, '<p><br><a><b><i><u><strong><em><span><sup><sub>');

//Strip attributes from tags (to prevent inline Javascript)
$dom = new DOMDocument();
$dom->loadHTML($description);
foreach($dom->getElementsByTagName('*') as $element)
{
    //Attributes cannot be removed directly because DOMNamedNodeMap implements Traversable incorrectly
    //Atributes are first saved to an array and then looped over later
    $attributes_to_remove = array();
    foreach($element->attributes as $name => $value)
    {
        if($name != 'style')
        {
            $attributes_to_remove[] = $name;
        }
    }

    //Loop over saved attributes and remove them
    foreach($attributes_to_remove as $attribute)
    {
        $element->removeAttribute($attribute);
    }
}
echo $dom->saveHTML();

這是DOMDocument :: loadHtml()的兩個選項,可以解決該問題。

$dom->loadHTML($description,  LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

但是它們僅在libxml> = 2.7.8中可用。 如果您使用的是舊版本,則可以嘗試其他方法:

如果您知道期望一個片段,則可以使用該片段並僅保存body元素的子元素。

$description = <<<'HTML'
<strong onclick="alert('evil');" style="text-align:center;">Evil</strong>
HTML;

$dom = new DOMDocument();
$dom->loadHTML($description);
foreach($dom->getElementsByTagName('*') as $element) {
    $attributes_to_remove = iterator_to_array($element->attributes);
    unset($attributes_to_remove['style']);
    foreach($attributes_to_remove as $attribute => $value) {
        $element->removeAttribute($attribute);
    }
}
foreach ($dom->getElementsByTagName('body')->item(0)->childNodes as $node) {
  echo $dom->saveHTML($node);
}

輸出:

<strong style="text-align:center;">Evil</strong>

我不知道這或多或少是您的意思...

$description = "<p><strong onclick=\"alert('evil');\">Evil</strong></p>";
$description = strip_tags( $description, '<p><br><a><b><i><u><strong><em><span><sup><sub>' );

$dom=new DOMDocument;
$dom->loadHTML( $description );
$tags=$dom->getElementsByTagName('*');

foreach( $tags as $tag ){
    if( $tag->hasAttributes() ){
        $attributes=$tag->attributes;
        foreach( $attributes as $name => $attrib ) $tag->removeAttribute( $name );
    }
}
echo $dom->saveHTML();
/* Will echo out `Evil` in bold but without the `onclick` */

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM