PHP中显示格式化的用户输入

你可以在这个页面下载这个文档附带的文件,也可以在文件下载中的字符处理中下载这个文档描述如何安全显示的有格式的用户输入。我们将讨论没有经过过滤的输出的危险,给出一个安全的显示格式化输出的方法。

没有过滤输出的危险

如果你仅仅获得用户的输入然后显示它,你可能会破坏你的输出页面,如一些人能恶意地在他们提交的输入框中嵌入javascript脚本:

This is my comment.
<script language="javascript:
alert('Do something bad here!')">.

这样,即使用户不是恶意的,也会破坏你的一些HTML的语句,如一个表格突然中断,或是页面显示不完整。

只显示无格式的文本

这是一个最简单的解决方案,你只是将用户提交的信息显示为无格式的文本。使用htmlspecialchars()函数,将转化全部的字符为HTML的编码。

如<b>将转变为<b>,这可以保证不会有意想不到的HTML标记在不适当的时候输出。
这是一个好的解决方案,如果你的用户只关注没有格式的文本内容。但是,如果你给出一些可以格式化的能力,它将更好一些。
Formatting with Custom Markup Tags
用户自己的标记作格式化

你可以提供特殊的标记给用户使用,例如,你可以允许使用[b]...[/b]加重显示,[i]...[/i]斜体显示,这样做简单的查找替换操作就可以了: $output = str_replace("[b]", "<b>", $output);
$output = str_replace("[i]", "<i>", $output);

再作的好一点,我们可以允许用户键入一些链接。例如,用户将允许输入[link="url"]...[/link],我们将转换为<a href="">...</a>语句

这时,我们不能使用一个简单的查找替换,应该使用正则表达式进行替换:
$output = ereg_replace('\[link="([[:graph:]]+)"\]', '<a href="\\1">', $output);

ereg_replace()的执行就是:
查找出现[link="..."]的字符串,使用<a href="..."> 替换它
[[:graph:]]的含义是任何非空字符,有关正则表达式请看相关的文章。

在outputlib.php的format_output()函数提供这些标记的转换,总体上的原则是:
调用htmlspecialchars()将HTML标记转换成特殊编码,将不该显示的HTML标记过滤掉,
然后,将一系列我们自定义的标记转换相应的HTML标记。
请参看下面的源代码:
<?php

function format_output($output) {
/****************************************************************************
* Takes a raw string ($output) and formats it for output using a special
* stripped down markup that is similar to HTML
****************************************************************************/

$output = htmlspecialchars(stripslashes($output));

/* new paragraph */
$output = str_replace('[p]', '<p>', $output);

/* bold */
$output = str_replace('[b]', '<b>', $output);
$output = str_replace('[/b]', '</b>', $output);

/* italics */
$output = str_replace('[i]', '<i>', $output);
$output = str_replace('[/i]', '</i>', $output);

/* preformatted */
$output = str_replace('[pre]', '<pre>', $output);
$output = str_replace('[/pre]', '</pre>', $output);

/* indented blocks (blockquote) */
$output = str_replace('[indent]', '<blockquote>', $output);
$output = str_replace('[/indent]', '</blockquote>', $output);

/* anchors */
$output = ereg_replace('\[anchor="([[:graph:]]+)"\]', '<a name="\\1"></a>', $output);

/* links, note we try to prevent javascript in links */
$output = str_replace('[link="javascript', '[link=" javascript', $output);
$output = ereg_replace('\[link="([[:graph:]]+)"\]', '<a href="\\1">', $output);
$output = str_replace('[/link]', '</a>', $output);

return nl2br($output);
}

?>

一些注意的地方:

记住替换自定义标记生成HTML标记字符串是在调用htmlspecialchars()函数之后,而不是在这个调用之前,否则你的艰苦的工作在调用htmlspecialchars()后将付之东流。

在经过转换之后,查找HTML代码将是替换过的,如双引号"将成为"

nl2br()函数将回车换行符转换为<br>标记,也要在htmlspecialchars()之后。

当转换[links=""] 到 <a href="">, 你必须确认提交者不会插入javascript脚本,一个简单的方法去更改[link="javascript 到 [link=" javascript, 这种方式将不替换,只是将原本的代码显示出来。

outputlib.php
在浏览器中调用test.php,可以看到format_output() 的使用情况

正常的HTML标记不能被使用,用下列的特殊标记替换它:

- this is [b]bold[/b]
- this is [i]italics[/i]
- this is [link="http://www.phpbuilder.com"]a link[/link]
- this is [anchor="test"]an anchor, and a [link="#test"]link[/link] to the anchor

[p]段落
[pre]预先格式化[/pre]
[indent]交错文本[/indent]

这些只是很少的标记,当然,你可以根据你的需求随意加入更多的标记

Conclusion
结论

这个讨论提供安全显示用户输入的方法,可以使用在下列程序中

留言板
用户建议
系统公告
BBS系统

(0)

相关推荐

  • PHP无限分类代码,支持数组格式化、直接输出菜单两种方式

    复制代码 代码如下: <?php /** +------------------------------------------------ * 通用的树型类 +------------------------------------------------ * @author yangyunzhou@foxmail.com +------------------------------------------------ * @date 2010年11月23日10:09:31 +-------

  • php实现的返回数据格式化类实例

    本文实例讲述了php实现的返回数据格式化类及其用法,在字符串处理中非常具有实用价值.分享给大家供大家参考.具体方法如下: DataReturn.class.php类文件如下: <?php /** 返回数据格式化类 * Date: 2011-08-15 * Author: fdipzone */ class DataReturn{ // class start private $type; private $xmlroot; private $callback; private $returnDa

  • 深入PHP nl2br()格式化输出的详解

    nl2br()函数可将字符串中的换行符转成HTML的换行符号 复制代码 代码如下: <?php $str = "最近几天一直在下雨,难过死了 ,球也打不成,鞋子也湿透了."; echo $str; echo "<br />"; echo nl2br($str); ?> 输出结果: 复制代码 代码如下: 最近几天一直在下雨,难过死了,球也打不成,鞋子也湿透了.最近几天一直在下雨,难过死了,球也打不成,鞋子也湿透了. 附:深入探讨"&l

  • PHP 防注入函数(格式化数据)

    复制代码 代码如下: <? //格式化数据(防止注入) function site_addslashes($string, $force = 0) { !defined('MAGIC_QUOTES_GPC') && define('MAGIC_QUOTES_GPC', get_magic_quotes_gpc()); if(!MAGIC_QUOTES_GPC || $force) { if(is_array($string)) { foreach($string as $key =&

  • PHP,ASP.JAVA,JAVA代码格式化工具整理

    PHP代码格式化工具http://www.waterproof.fr/products/phpCodeBeautifier/最近修改一个代码,里面完全没有缩进,用这个能够格式化一下.相当于以前c 的indent顺便写一下其他语言的c, c++ c# ==> indent Astylejava ==> astyle Jalopy Jacobe ImportScrbberphp ==> phpCodeBeautifierperl ==> perlTidypython ==> Py

  • 利用php递归实现无限分类 格式化数组的详解

    我们要做一个商品的无限分类首先数据库字段为:id ----------商品主键idfid ---------- 商品父idname ---------- 商品名最后输出的数组格式为 复制代码 代码如下: <PRE class=php name="code"><PRE class=php name="code">array( 0=>array(  'id'=>1,  'fid'=>0,  'name'=>'法国货'  '

  • php格式化日期和时间格式化示例分享

    复制代码 代码如下: // 格式化日期 static function formatDate($format, $datetime, $week = 0) {     $datetime = $datetime > 3000 ? $datetime : strtotime($datetime);     if ($week) {         $weeknames = [             '日',             '一',             '二',           

  • php 格式化数字的时候注意数字的范围

    构造sql语句是 比起来 复制代码 代码如下: $sql = 'SELECT * FROM sdb_comments WHERE goods_id = '.intval($goods_id).' AND for_comment_id IS NULL AND object_type = ".$item." AND disabled="false" AND display = "true"'; 我更喜欢这样做: 复制代码 代码如下: $sql = s

  • PHP数字格式化

    例如,echo number_format(285266237); 可以输出 285,266,237 另外如果需要格式化文件字节大小,下面的方法可以借鉴: function byte_format($input, $dec=0)    {      $prefix_arr = array(' B', 'K', 'M', 'G', 'T');     $value = round($input, $dec);     $i=0;     while ($value>1024)     {     

  • php自定义的格式化时间示例代码

    如:时间刚好是5分钟前,则对应的时间戳就会被格式化为5分钟前,不多说了,直接贴上代码: 复制代码 代码如下: /** * 格式化时间 * @param integer $timestamp 时间戳 * @param string $format dt=日期时间 d=日期 t=时间 u=个性化 其他=自定义 * @param integer $timeoffset 时区值 * @param string $custom_format 自定义时间格式 * @return string */ publ

随机推荐