`

URL 中,查询字符串与HTML实体冲突,可能带来的问题.

阅读更多

 

转自:http://www.cnblogs.com/_franky/archive/2012/09/28/2706512.html
IE10+, Safari5.17+, Firefox4.0+,Opera12+, Chrome7+ 已经按新标准实现. 所以就没有这个问题了.
 
参考标准 : http://www.w3.org/html/ig/zh/wiki/HTML5/tokenization  新标准明确提到,如果实体后面遇到的不是;且下一个是= 那么就不处理的.就是为了解决这个坑爹的问题的.

 

我们来看demo :

<a href="http://www.baidu.com?a=1&reg=2&reg_a=3" >悲剧</a>

 
部分浏览器(对应上面已经按新标准实现的版本之下的,各个浏览器.)
点上面的链接, 会自动把  &reg 转意成® (部分浏览器会自动对转意后的字符进行编码) .  
 
这个bug.的本质,就是当HTML中出现相关HTML实体(HTML character entity)时.就自动转意处理了. 所以理论上, 用脚本,动态创建的资源则没有这个问题,比如 new Image().src = 'http://www.baidu.com?a=1&reg=2'; 甚至动态创建的iframe.亦如此.
 
IE9- 有两个问题比其他浏览器更严重:
1. 用脚本跳转当前页比如location.href = xxx,或 location.replace(xxx) .又或者是调用window.open(xxx);如果查询字符串中包含这些html实体, 仍然会触发这个问题... 
2. ,参见标准, 你会知道实体+"其他字符"   ,    "其他字符中",哪些与实体连接在一起,是没有这个问题的. 比如 &rega  , &reg1     其中a, 1 与 &reg 连接就不会有这种问题,从标准角度,甚至是  &reg_a 也不应有问题. 但是IE9-又一次打败了我们.  至于其他特殊字符如 # ~ 等.在各个浏览器中表现各异. 考虑我们在设计字段名时,不大可能出现那些字符.我们也不再纠结其他浏览器在此处实现的差异.
 
 
 
所以,理论上,这个问题应该是后端的同学,在输出html时.更加要注意的问题.  而前端同学,要注意的则是跳转或弹窗时的url中是否有相关的字段包含一个无分号即为html实体的情况.
 
至于IE为啥这么特殊...我也没想明白...
 
那么,无论后端同学也好,前端同学也罢,我们可能更改已经定好的字段成本比较高.  所以其实最妥善的办法,应该是这样子: (感谢 @辰光未然 的提醒.)
var fixURL = function (url) {
    return url.replace(/&/g,'&amp;');
};
//使用fixURL 去替换url中的&.然后再输出给html, 或者跳转链接,又或者弹窗... 当然,前端的同学在js代码中之所以要这样做.主要是受IE的拖累...

  

 
 
 
 
 
 
 
那么大概,很多HTML 实体都会出问题:
 
 
这个表里, 没有分号结尾的,都是隐患...  也就是下面这106个: (感谢 @kenny 提供的最新的list 地址. 我花了点时间写了个脚本.把需要处理的,都抓了出来.)
 
 
我们可以用下面这个脚本来帮忙做检测 :
 
   var checkURL = function () {
    var list = [ //106
            '&Aacute',
            '&aacute',
            '&Acirc',
            '&acirc',
            '&acute',
            '&AElig',
            '&aelig',
            '&Agrave',
            '&agrave',
            '&AMP',
            '&amp',
            '&Aring',
            '&aring',
            '&Atilde',
            '&atilde',
            '&Auml',
            '&auml',
            '&brvbar',
            '&Ccedil',
            '&ccedil',
            '&cedil',
            '&cent',
            '&COPY',
            '&copy',
            '&curren',
            '&deg',
            '&divide',
            '&Eacute',
            '&eacute',
            '&Ecirc',
            '&ecirc',
            '&Egrave',
            '&egrave',
            '&ETH',
            '&eth',
            '&Euml',
            '&euml',
            '&frac12',
            '&frac14',
            '&frac34',
            '&GT',
            '&gt',
            '&Iacute',
            '&iacute',
            '&Icirc',
            '&icirc',
            '&iexcl',
            '&Igrave',
            '&igrave',
            '&iquest',
            '&Iuml',
            '&iuml',
            '&laquo',
            '&LT',
            '&lt',
            '&macr',
            '&micro',
            '&middot',
            '&nbsp',
            '&not',
            '&Ntilde',
            '&ntilde',
            '&Oacute',
            '&oacute',
            '&Ocirc',
            '&ocirc',
            '&Ograve',
            '&ograve',
            '&ordf',
            '&ordm',
            '&Oslash',
            '&oslash',
            '&Otilde',
            '&otilde',
            '&Ouml',
            '&ouml',
            '&para',
            '&plusmn',
            '&pound',
            '&QUOT',
            '&quot',
            '&raquo',
            '&REG',
            '&reg',
            '&sect',
            '&shy',
            '&sup1',
            '&sup2',
            '&sup3',
            '&szlig',
            '&THORN',
            '&thorn',
            '&times',
            '&Uacute',
            '&uacute',
            '&Ucirc',
            '&ucirc',
            '&Ugrave',
            '&ugrave',
            '&uml',
            '&Uuml',
            '&uuml',
            '&Yacute',
            '&yacute',
            '&yen',
            '&yuml'
        ];
        
    return function (url) {
        var l = list;
        var i = l.length;
        var matchIndex;
        var current;
        var nextchar;
        var errors = [];
        for (; i--;){
            matchIndex = url.indexOf(l[i]);
            current = l[i];
            if(matchIndex > -1){
                if((current === '&amp' || current === '&AMP') && url.charAt(matchIndex + 4) === ';'){
                    //如果是 &amp; 或 &AMP; 我们就认为是故意要输出 & ,比如是一个调用fixURL方法修正过的URL.里面的& 会被我们替换为 amp;
                    //所以,我们要跳过它,去检查后面.
                    continue;
                }
                nextchar = url.charAt(matchIndex + current.length);
                if(!/[a-zA-Z0-9]/.test(nextchar)){
                    //此处我们只要发现任意一个 ,如 &reg后面紧随字符不在 a-z,A-Z,0-9范围内.就算有问题.
                    //这样处理实际和标准的细节以及浏览器实现有细微差异. 但是本着任何浏览器来跑case,
//都能发现潜在威胁的原则.和实现复杂度的考虑.
                    // 我们姑且粗暴的这样处理了. 似乎还不错.
                     
                    errors.push(current + nextchar);
                }
            }
        }
        if(errors.length){
            throw Error('contains : \n' + errors.join('\n'));
        }
    };
}();

  

 
 
 
 
test case 1: 
var url  = '//www.baidu.com?a=1&amp=2&lt=3&reg=4';          
document.onclick = function () { //IE9-好了.证明我们的修正是ok的了.
      window.open(fixURL(url))
};

  


 
 test case 2:
var url  = '//www.baidu.com?a=1&amp=2&lt=3&reg=4';    
  try{
      checkURL(url);
  }catch(e){
      alert(e.message)
  }
 
 

 

分享到:
评论

相关推荐

    用友U8_EAI数据接口常见问题.doc

    - 检查适配器的连接字符串是否正确。 - 确认适配器使用的数据库驱动与企业管理器相同。 - 调整适配器配置,确保数据库连接参数无误。 #### 27. 适配器报错:对象不存在 - **解决方案**: - 确认对象名称是否...

    Java常见问题及处理.docx

    12. **MappingNotFoundException**:在Eclipse中,这可能是由于实体类的刷新问题或实体类不在指定目录中。确保Eclipse已更新项目,并正确配置了类路径。 13. **HibernateException**:找不到hibernate.cfg.xml配置...

    Javaweb常见错误.pdf

    核对数据库连接字符串的准确性。 5. **类路径没有找到**:这通常与ClassNotFoundException一起出现,表示运行时找不到特定的类。检查类路径是否包含相应的jar文件,特别是数据库驱动程序。 6. **空指针异常**:这...

    java常见错误集锦.pdf

    Java编程过程中,开发者经常会遇到各种错误,这些错误...以上错误分析和解决方法旨在帮助Java开发者诊断和修复他们在开发过程中可能遇到的问题。理解这些错误的原因并采取适当的措施可以提高开发效率并减少调试时间。

    .net auto generate url短链接

    为了防止哈希冲突,我们可能还需要配合使用数据库来存储原始URL与哈希值的映射关系。 创建短链接服务的第一步是设计数据库模型。这通常包括一个表,有两个字段:一个是短链接ID(哈希值),另一个是原始的长链接URL...

    ava常见错误以及可能原因集锦

    检查并确认连接字符串的准确性。 5. **类路径没有找到**:这个错误通常与ClassNotFoundException一起出现,表示无法找到指定的类。可能是类名写错、没有import导入或者jar文件不在类路径中。确保类路径设置正确,并...

    Java_web常见错误

    Java Web 开发中,开发者经常会遇到各种错误,这些错误可能是语法错误、逻辑错误或是环境配置问题。以下是一些常见的 Java Web 错误及其可能的原因和解决方法: 1. **需要标识符**:当代码中缺少变量、方法或类的...

    ASP.NET4高级程序设计第4版 带目录PDF 分卷压缩包 part1

    11.2.3 使用特定查询字符串参数的缓存 11.2.4 自定义缓存控制 11.2.5 使用HttpCachePolicy类进行缓存 11.2.6 缓存后替换和部分页缓存 11.2.7 缓存用户配置 11.2.8 缓存配置 11.2.9 输出缓存扩展 11.3...

    java常见错误集

    检查数据库连接字符串以确保数据库名称和服务器地址正确无误。 6. **类路径未找到**:当Java运行时找不到指定的类,可能是由于类路径设置不正确,类的包名错误,或者缺少相应的jar文件。确认所有依赖项已添加到类...

    HTML-CSS-JAVASCRIPT

    5. **ES6+新特性**:包括箭头函数、模板字符串、Promise对象、async/await用于异步编程,以及类和模块等,使代码更简洁、可维护。 这三者结合,可以构建功能丰富的现代网页。HTML定义结构,CSS赋予视觉样式,...

    java错误大全(包括基本异常和开源框架出现的异常)

    - **可能的原因**:数据库连接字符串错误。 - **解决方法**:检查数据库名称、IP地址和端口号是否正确无误。 5. **类路径没有找到** - **可能的原因**:类路径设置不正确或缺少必要的jar文件。 - **解决方法**...

    无废话XML.pdf 无废话XML.pdf

    - **2.1 数据类型**:讲解了XML中支持的各种数据类型,如字符串、数字等。 - **2.2 实体引用**:介绍了实体引用的概念,包括预定义实体和用户自定义实体。 - **2.3 CDATA段**:解释了CDATA段的作用,即用于标记XML...

    2021-2022计算机二级等级考试试题及答案No.550.docx

    11. C语言中的strlen函数计算字符串长度,不包括结束的空字符,所以"China"的长度是6,输出为6。 12. URL中的"http"表示访问协议,即超文本传输协议。 13. 在VFP系统环境下,运行表单的命令是DO FORM。 14. ...

    php面试测试

    以下是一些常见的面试问题及其答案,涵盖了表单提交方法、会话管理、输出控制、字符串操作、数据库优化等多个方面: 1. **GET与POST提交方法的区别** - GET:通过URL参数传递数据,限制了数据量,通常用于检索数据...

    ASP.NET4高级程序设计(第4版) 3/3

    11.2.3 使用特定查询字符串参数的缓存 363 11.2.4 自定义缓存控制 364 11.2.5 使用HttpCachePolicy类进行缓存 365 11.2.6 缓存后替换和部分页缓存 365 11.2.7 缓存用户配置 367 11.2.8 缓存配置 368 ...

    PHP面试试题及答案

    - POST方式:将表单数据作为实体数据发送,不显示在URL上,可以传输大量数据,安全性相对较高。 2. **Session与Cookie的区别** - Session:存储在服务器端,通常用于存储用户会话信息,如用户ID,保持登录状态等...

    2021-2022计算机二级等级考试试题及答案No.16111.docx

    - **知识点说明**:字符串操作是编程中常见的需求之一,包括提取子字符串等功能。 - **说明**:在给定的例子中,函数 `SUBSTR("VisualFoxPro5.0",7,6)` 返回的是从第7个字符开始长度为6的子字符串 “FoxPro”。 ###...

Global site tag (gtag.js) - Google Analytics