URL中,拼接字符串与浏览器转意冲突解决方案

本文探讨了HTML实体转义问题及其在不同浏览器中的表现,特别指出IE9及以下版本的特殊行为,并提供了修复方法及检测工具。讨论了如何避免URL中的HTML实体导致的问题,以及在IE中跳转或弹窗时的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

此问题相关信息(我不放在最前面,似乎有些朋友会找不到的样子.)

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,'&');
};
//使用fixURL 去替换url中的&.然后再输出给html, 或者跳转链接,又或者弹窗... 当然,前端的同学在js代码中之所以要这样做.主要是受IE的拖累...

那么大概,很多HTML 实体都会出问题:
 
 
这个表里, 没有分号结尾的,都是隐患...  也就是下面这106个: (感谢 @kenny 提供的最新的list 地址. 我花了点时间写了个脚本.把需要处理的,都抓了出来.)
 
 
我们可以用下面这个脚本来帮忙做检测 :
var checkURL = function () {
    var list = [ //106
            'Á',
            'á',
            'Â',
            'â',
            '´',
            'Æ',
            'æ',
            'À',
            'à',
            '&',
            '&',
            'Å',
            'å',
            'Ã',
            'ã',
            'Ä',
            'ä',
            '¦',
            'Ç',
            'ç',
            '¸',
            '¢',
            '©',
            '&copy',
            '¤',
            '°',
            '÷',
            'É',
            'é',
            'Ê',
            'ê',
            'È',
            'è',
            'Ð',
            'ð',
            'Ë',
            'ë',
            '½',
            '¼',
            '¾',
            '>',
            '>',
            'Í',
            'í',
            'Î',
            'î',
            '¡',
            'Ì',
            'ì',
            '¿',
            'Ï',
            'ï',
            '«',
            '<',
            '<',
            '¯',
            'µ',
            '·',
            ' ',
            '¬',
            'Ñ',
            'ñ',
            'Ó',
            'ó',
            'Ô',
            'ô',
            'Ò',
            'ò',
            'ª',
            'º',
            'Ø',
            'ø',
            'Õ',
            'õ',
            'Ö',
            'ö',
            '¶',
            '±',
            '£',
            '"',
            '"',
            '»',
            '®',
            '&reg',
            '§',
            '­',
            '¹',
            '²',
            '³',
            'ß',
            'Þ',
            'þ',
            '×',
            'Ú',
            'ú',
            'Û',
            'û',
            'Ù',
            'ù',
            '¨',
            'Ü',
            'ü',
            'Ý',
            'ý',
            '¥',
            'ÿ'
        ];
        
    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 === '&' || current === '&') && url.charAt(matchIndex + 4) === ';'){
                    //如果是 & 或 & 我们就认为是故意要输出 & ,比如是一个调用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&=2<=3&reg=4';           
document.onclick = function () { //IE9-好了.证明我们的修正是ok的了.
      window.open(fixURL(url))
};

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


<think>嗯,用户问的是如何通过URL传递参数以及常见问题和解决方案。首先,我得回顾一下URL传参的基本方法。记得URL参数通常是附加在路径后面,用问号分隔,键值对用等号连接,多个参数用&符号分开,比如?name=John&age=30。这部分应该没问题,但可能需要举例说明。 然后,用户可能遇到哪些问题呢?比如中文乱码,因为URL默认编码可能不支持中文,需要用到encodeURIComponent或者decodeURIComponent来处理。比如引用[1]提到用URLSearchParams获取参数,这可以解决部分问题,但可能需要更详细的步骤。还有日期参数的传递,引用[3]提到Java中传递日期的问题,可能需要建议将日期转为ISO字符串或者时间戳,避免格式问题。 另一个常见问题是参数丢失或截断,特别是特殊字符如&或#,这时候必须正确编码,避免被解析错误。比如在PHP中用urlencode,JS中用encodeURIComponent。引用[5]提到的uni-app路由传参参数丢失,可能涉及框架自身的问题,需要建议使用框架提供的API或全局事件通信。 还有跨平台或框架的问题,比如Vue或React中的路由传参,可能需要使用特定的方法如params或query,而不是直接拼接URL。比如引用[4]中的layui传参,用全局变量可能不够可靠,建议使用框架推荐的方式。 此外,不同后端处理方式不同,比如Spring MVC中@RequestMapping默认支持多种方法,但URL参数只支持GET,需要明确指定方法,如引用[2]提到的。可能还要提到POST等其他方法不适合URL传参。 安全问题也是要考虑的,比如敏感信息不应在URL中传递,容易被日志或浏览器历史记录截获。建议使用POST或加密,但用户的问题可能更关注技术实现,这部分可以简要提及。 总结下来,需要分步骤讲解传参方法,然后列出常见问题,每个问题对应解决方案,并引用相关的参考资料。需要确保语言口语化,避免技术术语堆砌,让用户容易理解。同时,注意用户提供的引用材料,正确关联到问题中,比如中文乱码对应引用[1],日期问题对应引用[3],框架问题对应引用[4]和[5],方法限制对应引用[2]。 最后,生成相关问题时要围绕URL传参的扩展,比如性能分析、优化方法、应用场景等,但根据用户提供的示例,可能包括编码必要性、特殊字符处理、不同框架传参方式、参数大小限制和安全性等。需要确保问题具有针对性,帮助用户深入理解。</think>### 如何通过URL传递参数及常见问题解决方案 #### 一、URL传参的基本方法 1. **基础语法** URL参数通过`?`附加在路径后,格式为`键=值`,多个参数用`&`分隔。例如: `https://example.com?name=John&age=30` 2. **动态生成参数** 在JavaScript中,可以使用`URLSearchParams`对象或`encodeURIComponent`函数编码参数,避免特殊字符冲突[^1]。 ```javascript let params = new URLSearchParams({ name: "张三", date: "2023-10-01" }); let url = `https://example.com?${params.toString()}`; ``` 3. **后端接收参数** 不同框架解析方式不同: - **Java Spring**:通过`@RequestParam`注解获取参数[^3]。 - **Node.js**:使用`querystring`模块解析URL参数。 --- #### 二、常见问题及解决方案 1. **中文乱码** **问题**:中文字符未编码导致乱码。 **解决**:使用`encodeURIComponent`编码,后端对应解码[^1]。 ```javascript let name = encodeURIComponent("张三"); // 编码 let decodedName = decodeURIComponent(urlParams.get("name")); // 解码 ``` 2. **日期参数传递** **问题**:日期格式解析错误或丢失。 **解决**:传递ISO标准格式(如`2023-10-01T12:00:00Z`)或时间戳。 ```java // Java示例:接收日期参数 @GetMapping("/event") public ResponseEntity<?> getEvent(@RequestParam("date") @DateTimeFormat(iso = ISO.DATE) LocalDate date) { // 业务逻辑 } ``` 3. **参数丢失或截断** **问题**:参数中包含`&`、`#`等特殊字符导致截断。 **解决**:严格编码所有参数,避免保留字符冲突。 ```javascript let param = encodeURIComponent("key=value&test=1"); // 输出 key%3Dvalue%26test%3D1 ``` 4. **跨平台/框架参数传递** **问题**:某些框架(如uni-app、layui)因路由机制导致参数丢失。 **解决**: - **uni-app**:使用`uni.$emit`和`uni.$on`全局事件通信[^5]。 - **layui**:通过父页面全局变量或`localStorage`传递参数[^4]。 5. **GET方法限制** **问题**:URL参数仅支持GET请求,且长度受限(通常不超过2048字符)。 **解决**: - 敏感数据改用POST请求。 - 超长参数拆分为多个请求或使用`POST + Body`[^2]。 --- #### 三、安全建议 1. **敏感信息避免URL传参** URL参数可能被浏览器历史记录或服务器日志截获,需加密或使用HTTPS。 2. **参数校验** 后端需对参数类型、范围做严格校验,防止SQL注入或非法访问。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值