浏览器和服务器解决传输中文数据的方法详解

主要内容

浏览器使用HTTP协议传输数据,HTTP协议要求请求的请求行和消息头都是字符串,且使用的文字对应的字符集只能是ISO8859-1.这是一个欧洲的字符集,不支持中文字符。在GET提交表单时可以从URL中的参数看到中文字符对应的形式:

GET /myweb/login?username=%E8%8C%83%E4%BC%A0%E5%A5%87&password=123456

这里的 % 表示这是一个中文字符,百分号后面对应的是一个中文字符对应的16进制数。
服务器获取到后按照以上规则反向编译得到相应字符集对应的中文!

详解

以登录页面为例,当我们在输入框中输入中文后点击登录,浏览器地址栏上可能看到的参数还是中文,但实际传递到服务端时,我们
解析请求行的抽象路径得到参数时,样子如下:
/myweb/login?username=%E8%8C%83%E4%BC%A0%E5%A5%87&password=123456
注:我们在用户名输入框里输入的是中文"范传奇"

为什么?
原因:提交表单时,抽象路径会被包含在请求的请求行中。
例如
GET /myweb/login?username=%E8%8C%83%E4%BC%A0%E5%A5%87&password=123456 HTTP/1.1

HTTP协议要求请求的请求行和消息头都是字符串,且使用的文字对应的字符集只能是ISO8859-1.这是一个欧洲的字符集。不支持中文字符。

怎么办?
曲线救国,想办法将不支持的中文用ISO8859-1支持的字符描述并传递给服务端。
首先:
ISO8859-1支持数字。
那么我们可以在浏览器中先将中文用UTF-8编码转换为2进制。

GET /myweb/login?username=范&password=123456 HTTP/1.1 不要允许!!!

例如:
“范”----UTF-8---->11101000 10001100 10000011(3个字节)

将2进制的1和0表达中文进行传递:
GET /myweb/login?username=111010001000110010000011&password=123456 HTTP/1.1
虽然问题得以解决。副作用是:太长!!! 1中文字符就需要24个1或0的字符来表达。

怎么缩短长度?
解决办法:将2进制用16进制表达,仍然可以满足需求。因为16进制可以用字符’0’-‘9’和’A’-‘F’

2进制 10进制 16进制
0000 0 0
0001 1 1
0010 2 2
0011 3 3
0100 4 4
0101 5 5
0110 6 6
0111 7 7
1000 8 8
1001 9 9
1010 10 A
1011 11 B
1100 12 C
1101 13 D
1110 14 E
1111 15 F

换成16进制后的样子:
11101000 10001100 10000011 "范"的UTF-8编码内容
E8 8C 83

GET /myweb/login?username=E88C83&password=123456 HTTP/1.1
原来需要用24个’0’或’1’字符的组合,现在仅需要6个字符就可以表达一个中文了

长度问题尽可能解决了,但是新的问题:如何与实际的英文数组组合区分开呢?
例如:
一个用于注册时取名字就叫:E88C83
此时,提交表单,地址为:GET /myweb/login?username=E88C83&password=123456 HTTP/1.1

服务端接收到该内容时:如何理解:E88C83
是当它为16进制数据,换算为2进制后用UTF-8还原为"范"
还是本来就是E88C83

为了解决混淆问题,URL地址格式要求,如果英文数字组合表达的是16进制内容,则每两位16进制前必须添加一个’%’
因此,实际传递中文名时应该如下:
GET /myweb/login?username=%E8%8C%83&password=123456 HTTP/1.1

如果时本来的英文数字组合应该如下:
GET /myweb/login?username=E88C83&password=123456 HTTP/1.1

揣测一个问题.如果改用输入的名字就叫:%E8%8C%83
这里实际上像:‘%’,‘?’,‘=’,'&'这些字符都属于URL的关键字符。当我们输入该字符传递时,浏览器会将该字符对应的1字节内容也以"%XX"转换。

在服务端进行反向还原时,直接使用java提供的API:
URLDecoder.decode()就可以转换了。
decode:解码

代码中我们在HttpServletRequest的parseParameters方法中将参数解码即可

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值