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 相关文章推荐
做个自己站内搜索引擎
Oct 09 PHP
国外PHP程序员的13个好习惯小结
Feb 20 PHP
PHP图片处理类 phpThumb参数用法介绍
Mar 11 PHP
PHP文件注释标记及规范小结
Apr 01 PHP
php实现的zip文件内容比较类
Sep 24 PHP
微信公众号点击菜单即可打开并登录微站的实现方法
Nov 14 PHP
ThinkPHP模版中导入CSS和JS文件的方法
Nov 29 PHP
Symfony实现行为和模板中取得request参数的方法
Mar 17 PHP
分享PHP-pcntl 实现多进程代码
Sep 30 PHP
阿里云Win2016安装Apache和PHP环境图文教程
Mar 11 PHP
python进程与线程小结实例分析
Nov 11 PHP
PHP使用PhpSpreadsheet操作Excel实例详解
Mar 26 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
mysql下创建字段并设置主键的php代码
2010/05/16 PHP
PHP--用万网的接口实现域名查询功能
2012/12/13 PHP
php生成缩略图填充白边(等比缩略图方案)
2013/12/25 PHP
使用PHP和HTML5 FormData实现无刷新文件上传教程
2014/09/06 PHP
浅谈PHP中output_buffering
2015/07/13 PHP
PHP正则验证字符串是否为数字的两种方法并附常用正则
2019/02/27 PHP
Laravel 实现关系模型取出需要的字段
2019/10/10 PHP
javascript 事件查询综合 推荐收藏
2010/03/10 Javascript
js操作checkbox遇到的问题解决
2013/06/29 Javascript
js实现卡片式项目管理界面UI设计效果
2015/12/08 Javascript
JavaScript jquery及AJAX小结
2016/01/24 Javascript
jQuery事件绑定用法详解
2016/09/08 Javascript
动态JavaScript所造成一些你不知道的危害
2016/09/25 Javascript
用p5.js制作烟花特效的示例代码
2018/03/21 Javascript
js构建二叉树进行数值数组的去重与优化详解
2018/03/26 Javascript
2种在vue项目中使用百度地图的简单方法
2018/09/28 Javascript
vue.js实现只能输入数字的输入框
2019/10/19 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
[59:42]Secret vs Alliacne 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
进一步探究Python中的正则表达式
2015/04/28 Python
Python_LDA实现方法详解
2017/10/25 Python
Python自动抢红包教程详解
2019/06/11 Python
python函数enumerate,operator和Counter使用技巧实例小结
2020/02/22 Python
Python使用shutil模块实现文件拷贝
2020/07/31 Python
pandas实现导出数据的四种方式
2020/12/13 Python
美国在线珠宝商店:SZUL
2017/02/11 全球购物
Needle & Thread官网:英国仙女品牌
2018/01/13 全球购物
德国网上宠物店:Zoobio
2018/05/23 全球购物
党支部公开承诺践诺书
2014/03/28 职场文书
《三顾茅庐》教学反思
2014/04/10 职场文书
小学家长评语大全
2014/04/16 职场文书
好学生评语大全
2014/05/05 职场文书
酒店管理专业自荐信
2014/05/23 职场文书
人代会标语
2014/06/30 职场文书
大学生暑期实践报告之企业经营管理
2019/08/08 职场文书
MySQL数据迁移相关总结
2021/04/29 MySQL