博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解决“在多字节的目标代码页中,没有此Unicode字符可以映射到的字符”
阅读量:6695 次
发布时间:2019-06-25

本文共 2118 字,大约阅读时间需要 7 分钟。

今天在处理Google网站管理员中的500错误时发现这样一些URL:

http://www.cnblogs.com/Garnai/tag/3D%3F%96%CA/http://www.cnblogs.com/henryfan/tag/%3F%3F%3F%90%B6%90%AC%3F%8C%8F/http://www.cnblogs.com/zhangpengshou/tag/%3F%96%DA%3F%97%9D%94V%8FC%3F/http://www.cnblogs.com/henryfan/tag/%3F%3F%3F%90%B6%90%AC%3F%8C%8F/...

这些URL不仅出现500错误,而且不显示自定义错误,只显示ASP.NET的默认错误页面:

运行时错误

服务器日志中记录具体的错误信息是:

[ArgumentOutOfRangeException: 在多字节的目标代码页中,没有此 Unicode 字符可以映射到的字符。 (异常来自 HRESULT:0x80070459)]   System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) +0   System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode) +13563503   System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name) +50   System.Web.Hosting.IIS7WorkerRequest.ReadRequestHeaders() +144   System.Web.Hosting.IIS7WorkerRequest.GetKnownRequestHeader(Int32 index) +109   System.Web.HttpWorkerRequest.HasEntityBody() +27   System.Web.HttpRequest.GetEncodingFromHeaders() +126   System.Web.HttpRequest.get_ContentEncoding() +162   System.Web.HttpRequest.get_QueryStringEncoding() +10   System.Web.HttpRequest.get_QueryStringText() +209   System.Web.HttpRequest.ValidateInputIfRequiredByConfig() +87   System.Web.PipelineStepManager.ValidateHelper(HttpContext context) +55

对应的英文错误信息是:

No mapping for the Unicode character exists in the target multi-byte code page.

从这些出错的URL中观察到了一个规律:都包含%3F这个编码,解码出来对应的字符是?。

从错误信息的代码执行堆栈信息 System.Web.HttpRequest.get_QueryStringText() 中,可以看出错误发生在从URL中读取查询字符串的时候。

可是出错的URL中并没有查询字符串。。。

后来突然想到,ASP.NET是先进行UrlDecode,然后再进行get_QueryStringText()的。

比如将  http://www.cnblogs.com/Garnai/tag/3D%3F%96%CA/ 进行URLDecode之后得到的URL是:

http://www.cnblogs.com/Garnai/tag/3D?柺/

看到没有,出现了问号,变成有查询字符串的URL。于是,ASP.NET将问号之后的字符作为key进行读取,由于key是不支持中文的,于是引发“在多字节的目标代码页中,没有此Unicode字符可以映射到的字符”。如果ASP.NET先进行get_QueryStringText(),再进行UrlDecode就不会触发这个问题,可是ASP.NET偏偏不这么干。

那如何解决这个问题?

虽然问题出在ASP.NET,但我们无法改变ASP.NET,只能另辟蹊径。

既然是ASP.NET处理上的问题,那我们别无选择,只能抢在ASP.NET之前拦截这样的URL请求,而进行这样的拦截最简单的工具就是IIS的Url Rewrite module。

根据我们的应用场景,在rewriteRules.config中添加一条规则——在URL中如果/tag/之后出现问号就直接返回404,规则定义如下:

然后就搞定了这个问题,写了这篇博客。 

你可能感兴趣的文章
LoadRunner使用之变量参数化
查看>>
asp.net运行原理
查看>>
canvas实现芝麻信用评分效果
查看>>
053(五十三)
查看>>
【Spark篇】---Spark中yarn模式两种提交任务方式
查看>>
最短路专题解题报告
查看>>
什么是FSO
查看>>
批处理程序如何接受多个文件拖入?开启了变量延迟enabledelayedexpansion之后遇到感叹号要怎么处理?...
查看>>
java中判断一个字符串是否“都为数字”和“是否包含数字”和“截取数字”
查看>>
Python 3
查看>>
实现主从关系Form中汇总行金额/数量
查看>>
Python学习笔记:协程
查看>>
原生js完成拼图小游戏
查看>>
[Algorithms] Radix Sort
查看>>
Eclipse打jar包的方法
查看>>
[WP7]关于退出时确认对话框的实现
查看>>
每日一记--迷茫
查看>>
mybatis like 查询
查看>>
Centos硬件信息
查看>>
Maven 打包
查看>>