双引号
在js代码中
在js中单、双引号引起来的是字符串,如果我们要在字符串中使用单、双引号,需要反斜杠进行转义
let str='user\'s name'; // or let str=" user's name"; // or let str="she said:\"...\".";
如果在字符串中输出反斜杠,仍然是用反斜杠转义,即2个反斜杠输出1个反斜杠
在html代码中
html标签中,属性值通常用双引号引起来,也可以使用单引号或不用引号。
<input name=user /> <input name="user" /> <input name='user' />
这3种写法都正确,不过通常我们是选择用双引号引起来。
如果我们要在属性值中使用单、双绰号,我们不能直接写成下面这样
<input name=user'name /> <input name="user"name" /> <input name='user'name' />
这些全部是错误的。我们要像在js中对单、双引号转义一样,对属性中的单、双引号转义
在html中输出预留符号,可以使用字符实体转义的形式,这里有简单介绍:http://www.w3school.com.cn/html/html_entities.asp。即想输出一个双引号可以使用"的形式,
<input name="user"name" />
除此之外,html还支持十进制与十六进制编码的形式输出字符,如我们知道字符a的ascii码的十进制是97 十六进制是61
所以我们在页面body中输出一个字符a,有以下3种形式
<body> a<!--直接输出--> a<!--十进制输出--> a<!--十六进制输出--> </body>
同样,单双引号也有十进制(单:39,双:34)与十六进制(单:27,双:22),所以我们在属性中输出一个单引号有2种选择,十进制与十六进制
<input name='user'name' /><!--十进制--> <input name='user'name' /><!--十六进制-->
而输出一个双引号则有3种选择
<input name="user"name" /><!--实体--> <input name="user"name" /><!--十进制--> <input name="user"name" /><!--十六进制-->
当js代码遇上实体编码
我们可以通过dom节点提供的事件写上调用js的代码,如点击body弹出hello这个字符串,我们可以写成
<body onclick="alert('hello')">
click here
</body>
如果我们的需求是就弹出一个双引号呢?
根据前述规则,我们要写成:
<body onclick="alert('"')"><!--这里用十进制或十六进制都可以-->
click here
</body>
当然,alert里的单引号也可以使用十进制或十六进制编码
<body onclick="alert("'")"><!--"单引号 '双引号-->
click here
</body>
这样也是可以的。
是不是有点xss的感觉?
如果我们把弹双引号的需求改成单引号呢?
<body onclick="alert(''')"><!--这样html中是合法的,但js中并不合法,因为在js中,中间的单引号并没有转义-->
click here
</body>
如果我们用十进制或十六进制编码呢?
<body onclick="alert('"')"><!--这样可以吗-->
click here
</body>
这样仍然是不可以的
我们要对js字符串中的单引号进行转义,如
<body onclick="alert('\'')"><!--转义后可正确弹出-->
click here
</body>
或
<body onclick="alert('\"')"><!--转义后可正确弹出-->
click here
</body>
前面的onclick="alert('\'')"看起来还正常,后面的这个onclick="alert('\"')"就有点不直观了。因为后面这个看上去反斜杠像在转义&这1个字符,而&在js的字符串中并不需要转义的。
动态输出
如前述的alert弹出的消息,如果是一个变量控制,动态输出呢?
<body onclick="alert('${msg}')">
click here
</body>
那我们这个msg字符串就得注意了,从这个示例来看,这个动态的msg即出现在属性onclick中,也出现在alert的单引号开始的字符串中。
我们要对msg中的双引号转成"或"或",并对msg中单引号的前面加上一个反斜杠\ ?
题外话:对msg中的反斜杠需要做double处理,因为反斜杠在html属性中并不是特殊的,但在js的字符串中是特殊的。因此正确的做法是对反斜杠及单引号前面各加上一个反斜杠
然而,你并不能保证属性是用双引号,alert中的字符串用的是单引号,因为可以写成下面这样
<body onclick='alert("${msg}")'>
click here
</body>
?
这种情况我们要对msg中的单引号转成'或',并对msg中双引号前面加上一个反斜杠\
题外话:同上
看上去要根据不同的情况做不同的处理,其实也不需要
我们只需要对单、双引号前面加上一个反斜杠\然后再对单、双引号实体编码即可。
在js中如果反斜杠后面跟的不需要反斜杠转义的字符,那么这个反斜杠是被丢弃的,因此像
var str="user\'s name";
单引号前面多加一个反斜杠也不要紧的。
自动化处理与识别提醒
在magix项目中,由于magix-combine的支持,可识别出属性中js代码的部分,并自动化处理,如
<button mx-click="showName({name:'<%=name%>'})">click here</button>
name这个变量可包含任意的单、双引号及反斜杠。工具自动识别并处理,开发者不需要做任何事情。
而对于这样的写法:
<button mx-click="showName({name:'"'})">click here</button>
<!-- or-->
<button mx-click="showName({name:'\"'})">click here</button>
第一种写法其实并不正确,但第二种情况看上去又怪怪的。magix-combine工具能识别出来是否需要添加反斜杠,并自动添加处理。
第一种需要添加反斜杠,工具会自动加上,并提醒开发者这里的写法是不正确的。
第二种说明开发者意识到了问题所在,自己处理了,工具就不再处理也不再提醒开发者。
近在练习TP3.2制作个人博客时,在后台中使用ueditor发布文章并保存在数据库中。
如下图,文章内容非常简单一段文字加一个图片,后台中可以对文章进行修改:传入文章ID->读取数据库->在ueditor中显示,这些操作都没有问题。
长沙蒲公英网络
在前台调用时却发现文章内容未正常显示--显示成了HTML实体的形式。考虑到文章内容在后台中显示正常,区别在于有无有使编程器。所以问题可能是编辑器保存数据时可能与通常形式不一样。
长沙蒲公英网络
通过查看数据库中文章内容保存的结果得知,编辑器将HTML标签进行了转义后再保存,而输出到HTML页面中时,标签被转义回单独的字符直接显示成了HTML代码。这样处理的优点是可以避免sql注入;缺点是不能直接读取数据。
长沙蒲公英网络
知道了原因,那么问题解决起来就容易多了。1.高手可以对ueditor数据处理方式进行修改(时间成本高,可能导致sql注入的漏洞);2.可以将文章内容先读取在ueditor中,再把ueditor中的内容显示在页面上(过程复杂,但简单有效);3.读取数据时先处理后,再在模板中进行显示(简单实用)。
这里简单说明下第三种方法:在读取数据后使用html_entity_decode函数把文章内容从 HTML 实体转换为字符。
public function index() {
$id = I('get.id', '', 'intval');
$field = array('id', 'title', 'time', 'content', 'cid', 'click');
$blog = M('blog')->field($field)->find($id);
$blog['content'] = html_entity_decode($blog['content']);
$blog['click'] += 1;
$where = array('id' => $id);
M('blog')->where($where)->setInc('click');
$this->assign('blog', $blog);
$this->display();
}
通过以上处理后,文章内容就可以在前台正常使用了。
长沙蒲公英网络
原创文章链接:http://www.0731pgy.com/a/news/IndustryNews/430.html
*请认真填写需求信息,我们会在24小时内与您取得联系。