php 解码 mysql_real_escape_string() 以输出 HTML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2573332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:58:26  来源:igfitidea点击:

Decoding mysql_real_escape_string() for outputting HTML

phpsql-injectionhtml-encodemysql-real-escape-string

提问by Peter Craig

I'm trying to protect myself from sql injection and am using:

我正在尝试保护自己免受 sql 注入的影响,并且正在使用:

mysql_real_escape_string($string);

When posting HTML it looks something like this:

发布 HTML 时,它看起来像这样:

<span class="\&quot;className\&quot;">
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p>
</span>

I'm not sure how many other variations real_escape_string adds so don't want to just replace a few and miss others... How do I "decode" this back into correctly formatted HTML, with something like:

我不确定 real_escape_string 添加了多少其他变体,所以不想只替换一些而错过其他变体...如何将其“解码”回正确格式的 HTML,例如:

html_entity_decode(stripslashes($string));

回答by zombat

The mysql_real_escape_string()manual page tells you which characters are escaped:

mysql_real_escape_string()手册页告诉你哪些字符转义:

mysql_real_escape_string() calls MySQL's library function mysql_real_escape_string, which prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a.

mysql_real_escape_string() 调用 MySQL 的库函数 mysql_real_escape_string,它在以下字符前加上反斜杠:\x00、\n、\r、\、'、" 和 \x1a。

You could successfully reverse the escaping by replacing those escaped characters with their unescaped forms.

您可以通过用未转义的形式替换这些转义字符来成功逆转转义。

mysql_real_escape_string()shouldn't be used to sanitize HTML though... there's no reason to use it before outputting web page data. It should only be used on data that you're about to put into the database. Your sanitization process should look something like this:

mysql_real_escape_string()虽然不应该用于清理 HTML...但在输出网页数据之前没有理由使用它。它应该只用于您将要放入数据库的数据。您的消毒过程应如下所示:

Input

输入

  1. Accept user input from a form or HTTP request
  2. Create database query using mysql_real_escape_string()
  1. 接受来自表单或 HTTP 请求的用户输入
  2. 使用创建数据库查询 mysql_real_escape_string()

Output

输出

  1. Fetch data out of the database
  2. Run any user-defined data through htmlspecialchars()before printing
  1. 从数据库中取出数据
  2. htmlspecialchars()在打印之前运行任何用户定义的数据

Using a different database driver such as MySQLior PDOwill allow you to use prepared statements, which take care of escaping most inputs for you. However, if you can't switch or take advantage of those, then definitely use mysql_real_escape_string()... just only use it before inserting data.

使用不同的数据库驱动程序(例如MySQLiPDO)将允许您使用准备好的语句,它会为您转义大多数输入。但是,如果您不能切换或利用这些,那么一定要使用mysql_real_escape_string()......只在插入数据之前使用它。

回答by Your Common Sense

You got everything messed up.

你把一切都搞砸了。

mysql_real_escape_string don't need any decoding.

mysql_real_escape_string 不需要任何解码。

if you get your data back with slashes, it means that it has been escaped twice. And instead of stripping out the extra slashes you should just not to add them.

如果你用斜杠取回你的数据,这意味着它已经被转义了两次。而不是去掉额外的斜线,你不应该添加它们。

Not to mention that whatever escaping is obsoleted and you ought to

更不用说任何逃避的东西都已经过时了,你应该

use prepared statements

使用准备好的语句

instead of whatever escape string.

而不是任何转义字符串。

So, never escape, never decode.
The problem solved.

所以,永远不要逃避,永远不要解码。
问题解决了。

回答by Guss

mysql_real_escape_stringis used to prevent SQL injection when storing user provided data into the database, but a better method would be to use data binding using PDO(for example). I always recommend using that instead of messing with escaping.

mysql_real_escape_string用于在将用户提供的数据存储到数据库时防止 SQL 注入,但更好的方法是使用PDO(例如)使用数据绑定。我总是建议使用它而不是搞乱转义。

That being said, regarding your question on how to display it afterwards - after the data is stored, when you retrieve it the data is complete and valid without any need to be "unescaped". Unless you added your own escaping sequences, so please don't do that.

话虽如此,关于您之后如何显示它的问题 - 在存储数据之后,当您检索它时,数据是完整且有效的,无需“转义”。除非您添加了自己的转义序列,否则请不要这样做。

回答by Cups

Not sure what is going on with the formatting as I can see it but your html form

不确定格式是怎么回事,因为我可以看到它,但是您的 html 表单

<span class="\&quot;className\&quot;">
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p>
</span>

should be simply;

应该是简单的;

<span class="className">
<p class="pClass" id="pId"></p>
</span>

When you get it back, before you put it into the database you escape it using mysql_real_escape_string() to make sure you do not suffer an sql injection attack.

当您取回它时,在将其放入数据库之前,您使用 mysql_real_escape_string() 对其进行转义,以确保您不会遭受 sql 注入攻击。

Hence you are escaping the values ready for place the text is going next.

因此,您正在逃避准备好放置文本接下来的值。

When you get it out of the database ( or display ANY of it to users as html) then you escape it again ready for that that place it is going next (html) with htmlentities() etc to protect your users from XSS attacks.

当您将其从数据库中取出(或将其中的任何内容作为 html 显示给用户)时,您再次将其转义,准备好使用 htmlentities() 等方法将其转义到下一个位置(html),以保护您的用户免受 XSS 攻击。

This forms the EO part of the mantra FIEO, Filter Input, Escape Output, which you should tatoo on the inside of your eyelids.

这构成了咒语 FIEO、过滤器输入、逃逸输出的 EO 部分,你应该在眼睑内侧纹身。

回答by HELPFUL_SHADOW

I was wondering why this routine doesn't have a accompanying decoder routine. Its probably interpreted by MySQL the exact same way as if it were not escaped. You get the un-escaped results when you do a $row=mysql_fetch_array($res, MYSQL_ASSOC)';

我想知道为什么这个例程没有伴随的解码器例程。它可能被 MySQL 以完全相同的方式解释,就好像它没有被转义一样。当您执行以下操作时,您会得到未转义的结果$row=mysql_fetch_array($res, MYSQL_ASSOC)';

回答by Muhwu

Well, I took a stab at this the old fashion way and so far I am unable to see anything wrong with my approach. Obviously it's a bit crude but it gets the job done:

好吧,我以旧时尚的方式尝试了这种方式,到目前为止,我看不出我的方法有什么问题。显然它有点粗糙,但它完成了工作:

function mysql_unreal_escape_string($string) {
    $characters = array('x00', 'n', 'r', '\', '\'', '"','x1a');
    $o_chars = array("\x00", "\n", "\r", "\", "'", "\"", "\x1a");
    for ($i = 0; $i < strlen($string); $i++) {
        if (substr($string, $i, 1) == '\') {
            foreach ($characters as $index => $char) {
                if ($i <= strlen($string) - strlen($char) && substr($string, $i + 1, strlen($char)) == $char) {
                    $string = substr_replace($string, $o_chars[$index], $i, strlen($char) + 1);
                    break;
                }
            }
        }
    }
    return $string;
}

This should cover most cases.

这应该涵盖大多数情况。

回答by Peter

Even if it's an old question... I've had the same problem than Peter Craig. In fact I've to deal with an old CMS. In order to prevent SQL Injection, all $_POST and $_GET values are "sql-escaped". Unfortunatly this is done in a central point so all your modules are receiving all data sql-escaped! In some cases you want to directly display these data so you face a problem: how to display a sql-escaped string without gettng it from DB? The answer is: use stripcslashes (NOT stripslashes!!)

即使这是一个老问题……我和 Peter Craig 遇到了同样的问题。事实上,我必须处理旧的 CMS。为了防止 SQL 注入,所有 $_POST 和 $_GET 值都是“sql-escaped”。不幸的是,这是在一个中心点完成的,因此您的所有模块都在接收所有 sql 转义数据!在某些情况下,您想直接显示这些数据,因此您面临一个问题:如何在不从 DB 中获取它的情况下显示 sql 转义字符串?答案是:使用stripcslashes(不是stripslashes!!)

http://php.net/manual/en/function.stripcslashes.php

http://php.net/manual/en/function.stripcslashes.php

回答by Nandkishor Gokhe

use the following function to remove slashes while showing on HTML page:

使用以下函数在 HTML 页面上显示时删除斜线:

stripslashes();

带斜线();

eg. $html=stripslashes($html); OR $html=stripslashes($row["fieldname"]);

例如。$html=stripslashes($html); 或 $html=stripslashes($row["fieldname"]);

回答by Cryophallion

I think a number of other answers missed the obvious issue...

我认为其他一些答案忽略了明显的问题......

You are using mysql_real_escape_string on the inputted content (as you should if not using prepared statements).

您在输入的内容上使用 mysql_real_escape_string (如果不使用准备好的语句,您应该这样做)。

Your issue is with the output.

你的问题是输出。

The current issue is that you are calling html_entity_decode. Just stripslashes is all you need to restore the original text. html_entity_decode is what is messing up your quotes, etc, as it is changing them. You actually want to output the html, not just plain text (which is when you would use html_entities, etc). You are decoding something you want encoded.

当前的问题是您正在调用 html_entity_decode。只需使用stripslashes即可恢复原始文本。html_entity_decode 是什么弄乱了你的报价等,因为它正在改变它们。您实际上想要输出 html,而不仅仅是纯文本(这是您使用 html_entities 等的时候)。你正在解码你想要编码的东西。

If you only want the text version to show up, you can use the entities. If you are worried about bad tags, use striptags and allow only the tags you want (such as b, i, etc).

如果您只想显示文本版本,则可以使用实体。如果您担心坏标签,请使用 striptags 并只允许您想要的标签(例如 b、i 等)。

Finally, remember to encode and decode in the proper order. if you ran mysql_real_escape_String(htmlentities($str)), then you need to run html_entity_decode(stripslashes($str)). The order of operations matters.

最后,记得按正确的顺序进行编码和解码。如果您运行 mysql_real_escape_String(htmlentities($str)),那么您需要运行 html_entity_decode(stripslashes($str))。操作顺序很重要。

UPDATE: I did not realize that html_entity_decode also strips out slashes. It was not clearly documented on that page, and I just never caught it. I will still automatically run it though, as most html that I present I want left as entities, and even when I don't, I prefer to make that decision outside of my db class, on a case by case basis. That way, I know the slashes are gone.

更新:我没有意识到 html_entity_decode 也会去掉斜杠。该页面上没有明确记录,我只是从未发现过。不过,我仍然会自动运行它,因为我呈现的大多数 html 都希望保留为实体,即使我不这样做,我也更愿意在我的 db 类之外根据具体情况做出决定。这样,我知道斜线消失了。

It appears the original poster is running htmlentities (or his input program, like tinymce is doing it for him), and he wants to turn it back to content. So, html_entity_decode($Str) should be all that is required.

看起来原始海报正在运行 htmlentities(或他的输入程序,就像 tinymce 为他做的那样),他想把它转回内容。所以, html_entity_decode($Str) 应该是所有需要的。