1、邮件查收组件编码问题
之前开发过程中遇到的,使用一个开源的邮件组件,除了重构的时候误用了多线程,查收邮件并解析某些邮件内容的时候还发现死活都是乱码,然后分析邮件组件源码才知道,这个邮件类库使用UTF-8格式的编码,而我们查收的用户邮件很多都不是UTF-8格式的,而且还有一些多语言格式的邮件,比如俄语和日语,使用UTF-8解析也会碰到乱码问题。
2、截取字符串长度问题
一个很简单的函数,按照输入长度截取字符串,一个汉字算两个字符。
使用这个函数的时候,开发和测试环境都是通过的,但是生产环境发现截取的字符串就是不正确。最后发现这个函数的内部通过System.Text.Encoding.Default.GetByteCount(str)的方式获取单字节字符长度。Encoding.Default静态属性是用于获取操作系统的当前ANSI代码页的编码,开发和测试没有问题而生产有问题毫无疑问是因为操作系统的编码设置不同造成的。后来该函数改造成强制使用GB2312格式的编码,问题没有重现。
3、子系统或异构系统或内外部系统页面跳转编码问题
虽然页面交互的时候,很多系统之间的“切换”没有显式传人编码,但很多浏览器非常智能(实际可通过请求上下文得到具体编码,比如Asp.Net中通过HttpContext.Current.Request.ContentEncoding.BodyName确定当前编码方式),可以很轻松识别系统编码或者使用默认编码(),自动做出切换,所以有时候你不能很明显发现问题。
但是对于需要编程实现一些业务的时候,不同编码问题不能不考虑进去。比如你使用WebClient进行编程访问页面的时候,如果指定编码不正确,乱码了吧?猜对了。
还有一个简单的例子,比如电商网站接入第三方支付:
在网站接入支付宝支付的时候,发现用户从支付宝支付完成后,跳转回到当前网站总是验证签名不通过。支付宝提供的接入文档只是说,“在通知返回参数列表中,除去sign、sign_type两个参数外,凡是通知返回回来的参数皆是要签名的参数”。然后你按照NameValueCollection解析构造签名,发现返回的签名就是不正确,哪怕自己加上input_charset(这个参数支付宝没有显式返回,但是发起支付请求跳到支付宝的时候,我们使用的是UTF-8编码格式)参与签名也不行。
后来尝试使用下面这种方式通过GB2312解码构造签名排序数组,竟然就通过了。
foreach (var item in collection.AllKeys) { if (item == AlipayField.sign) { continue; } if (item == AlipayField.sign_type) { continue; } //支付宝页面同步返回的数据是用GBK编码的 sortedList.Add(item, HttpUtility.UrlDecode(collection[item], Encoding.GetEncoding("GB2312"))); }
原来支付宝页面同步返回的数据是用GBK编码的,也就是说你提交请求给支付宝input_charset使用的是UTF-8编码,支付宝页面同步返回的是GBK编码,而且支付宝不会把input_charset显式返回。
对比一下财付通,财付通打破了这个潜规则,页面同步通知的时候直接显式返回input_charset,验签的时候按照财付通传人的编码方式进行解码。
最后就是asp.net编码和解码,推荐使用系统自带HttpUtility这个实用类,最好不要自己搞封装,尤其是很可能无意识地引入了web请求上下文HttpConext.Current的编码方法,说不定那天就会碰到问题。
参考:http://www.cnblogs.com/xiaomia/archive/2010/11/28/1890072.html