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


Posted in PHP onOctober 09, 2006

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

没有过滤输出的危险

如果你仅仅获得用户的输入然后显示它,你可能会破坏你的输出页面,如一些人能恶意地在他们提交的输入框中嵌入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系统

PHP 相关文章推荐
PHP 组件化编程技巧
Jun 06 PHP
php 图片加水印与上传图片加水印php类
May 12 PHP
php根据isbn书号查询amazon网站上的图书信息的示例
Feb 13 PHP
PHP获取文件夹内文件数的方法
Mar 12 PHP
PHP贪婪算法解决0-1背包问题实例分析
Mar 23 PHP
php程序内部post数据的方法
Mar 31 PHP
Laravel实现构造函数自动依赖注入的方法
Mar 16 PHP
微信自定义菜单的创建/查询/取消php示例代码
Aug 05 PHP
php array_values 返回数组的值实例详解
Nov 17 PHP
Laravel框架中VerifyCsrfToken报错问题的解决
Aug 30 PHP
浅谈PHP实现大流量下抢购方案
Dec 15 PHP
php爬取天猫和淘宝商品数据
Feb 23 PHP
提升PHP执行速度全攻略(下)
Oct 09 #PHP
PHP的面向对象编程
Oct 09 #PHP
PHP文本数据库的搜索方法
Oct 09 #PHP
PHP:风雨欲来 路在何方?
Oct 09 #PHP
用Socket发送电子邮件(利用需要验证的SMTP服务器)
Oct 09 #PHP
用PHP实现登陆验证码(类似条行码状)
Oct 09 #PHP
用PHP创建PDF中文文档
Oct 09 #PHP
You might like
PHP3 safe_mode 失效漏洞
2006/10/09 PHP
PHP 日期加减的类,很不错
2009/10/10 PHP
PHP入门教程之上传文件实例详解
2016/09/11 PHP
List the Codec Files on a Computer
2007/06/18 Javascript
YUI Compressor压缩JavaScript原理及微优化
2013/01/07 Javascript
jQuery 删除或是清空某个HTML元素示例
2014/08/04 Javascript
AngularJS实现Model缓存的方式
2016/02/03 Javascript
JavaScript:Date类型全面解析
2016/05/19 Javascript
jquery 将当前时间转换成yyyymmdd格式的实现方法
2016/06/01 Javascript
angular内置provider之$compileProvider详解
2017/09/27 Javascript
axios+Vue实现上传文件显示进度功能
2019/04/14 Javascript
解决LayUI加上form.render()下拉框和单选以及复选框不出来的问题
2019/09/27 Javascript
JS 图片压缩原理与实现方法详解
2020/04/29 Javascript
vue实现简单计算商品价格
2020/09/14 Javascript
vue实现简易计算器功能
2021/01/20 Vue.js
[01:02:09]Liquid vs TNC 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.21
2020/07/19 DOTA
简单文件操作python 修改文件指定行的方法
2013/05/15 Python
Python列表(list)常用操作方法小结
2015/02/02 Python
python实现SMTP邮件发送功能
2020/06/16 Python
python MySQLdb使用教程详解
2018/03/20 Python
python 实现A*算法的示例代码
2018/08/13 Python
Numpy截取指定范围内的数据方法
2018/11/14 Python
Django 内置权限扩展案例详解
2019/03/04 Python
Django框架登录加上验证码校验实现验证功能示例
2019/05/23 Python
详解python深浅拷贝区别
2019/06/24 Python
Spring实战之使用util:命名空间简化配置操作示例
2019/12/09 Python
python实现飞机大战项目
2020/03/11 Python
使用Keras画神经网络准确性图教程
2020/06/15 Python
简述进程的启动、终止的方式以及如何进行进程的查看
2014/02/20 面试题
一句话工作感言
2014/03/01 职场文书
铁路安全事故反思
2014/04/26 职场文书
测控技术自荐信
2014/06/05 职场文书
建筑工地质量标语
2014/06/12 职场文书
搞笑的爱情检讨书
2014/10/01 职场文书
Python中的 enumerate和zip详情
2022/05/30 Python
Python使用Beautiful Soup(BS4)库解析HTML和XML
2022/06/05 Python