Web应用中浏览器与服务端的编码和解码

简介: Web应用中浏览器与服务端的编码和解码

【1】基本概念

有信息交换就会产生编码、传输、解码三个过程。编码是信息从一种形式转变成另一种形式的过程,正如人类的语言通过声带编码,转换成声波。解码是编码的逆函数,耳膜接收声波,通过脑神经解码成人类文化所能理解的信息。


字符集是一种文化上下文下的所有文字符号集合,它的作用是规定了某个文化下的所有字符,以及该字符在信息交换系统下的表示方式,在计算机信息系统下是字节或01序列。


对于java web应用,狭隘的编码解码的过程可以简单的理解为:编码的过程是文本字符串信息编码成01序列,解码是将01序列恢复为文本字符串信息,具体编码成什么样的01序列是由编码采用的字符集来决定的,也就是编码方案。


乱码是对信息采用的编码方案无法理解,使用了错误的编码方案对信息进行解码造成的。如果要理解一段信息的真实意图,就得知道信息采用的编码方案,这是信息交换的密钥,这就是为什么战争年代破解对方电报加密方式,实际上就是在破译对方的编码方案。

【2】浏览器端的编码

① http协议层的编码解码

http协议层的字符集关系到http发送者和接送者采用什么字符集方案解析对方发送的内容。

② 浏览器端的编码

请求端常规请求方式主要为form、url、ajax、http组件如HttpClient API。


浏览器存在文档编码方案charset的概念,文档的编码方案等同于文档解码方案,它对文档中发生的请求编码会产生影响。


影响form提交数据的编码的因素包括:form的accept-charset属性、html文档的编码方案即document.charset。其中,form的accept-charset是否能够有效,依赖具体浏览器的实现,有些浏览器并不支持,如IE。文档编码方案可以通过document.charset来修改。


文档内的url编码,如iframe的src指定的url,以文档编码方案为准,地址栏的url的编码方案完全取决于具体的浏览器实现,通过HttpClient组件发送请求时,url是能任意指定编码方案的。


ajax发送http请求的url编码方式完全取决于浏览器实现,一般支持以文档编码方案来决定,但是数据体统一采用utf-8,另外,虽然ajax可以指定header在content-type说明编码方案,但这种做法不会对url、数据体的编码方案产生任何影响,甚至在有些浏览器中,最终content-type中的编码描述都无法真正影响。


另外,header的默认编码方案是iso-8859-1,这个是http规范。

【3】服务端的解码

服务端的httpserver需要解码的对象包括:header、url、数据体。

  • header解码方案是iso-8859-1。
  • url解码方案通常称为URIEncoding,一般HttpServer会提供相应设置,标准servlet并不提供该接口。jetty默认utf-8字符集来解码,但其他httpserver如tomcat会默认iso-8859-1。
  • 数据体解码在servlet中可以通过request.setCharacterEncoding来设置。一般的,有些httpserver会以characterEncoding>request请求头字符集>utf-8的优先顺序来决定数据体的解码方案。


web服务器接收到客户端的请求后,会将其内容转给web容器来处理;因为接到的请求path(url)是编码过的二进制流,所以在处理前会将其转换成ASCII码 。但是请求中可能还有部分参数和消息体的数据是经过编码的(例如中文字符被编码),这里就涉及到对请求内容和参数进行解码的问题。


Servlet服务器实现的Servlet遇到URL和POST提交的数据中含有%的字符串,它会按照指定的字符集解码。


下面两个Servlet方法返回的结果都是经过解码的:

request.getParameter("name");
request.getPathInfo();

这里所说的"指定的字符集"是在应用服务器的配置文件中配置。默认为ISO-8859-1。

【4】服务端的编码

服务端解码是针对请求而言,服务端编码是针对响应而言。服务端httpserver需要编码的对象是:header、数据体。


header的编码方案同样是iso-8859-1。


通常情况下,服务端必须要指定返回数据体的编码方案且要在header中标注编码方案,否则httpserver一般默认iso-8859-1对输出进行编码,而浏览器也无法得知返回数据体的编码方案,只能自行猜测,完全依赖浏览器自己的实现。


response.setCharacterEncoding的职能是告诉httpserver数据体的编码方案,并不会也不应该影响到header中的编码方案的标注。

response.setContentType会影响到header的编码方案的标注,浏览器根据该标识决定解码方案。


对于一个健全的httpserver来说,在同时通过两个方法指定了数据体编码方案和header编码方案标注的情况下,数据体编码方案应该由后者决定,这样使浏览器端得到的编码信息和服务端真正编码信息一致。


另外,一定要注意的是这两个指定编码方案的方法必须在response创建输出流之前调用,输出流一旦创建,编码方案无法后期指定。


【5】浏览器端的解码

浏览器端的解码针对的是服务器返回的响应。浏览器端对返回进行解码的对象包括:header、数据体:

  • header的解码方案是iso-8859-1。
  • 浏览器的数据体解码方案依赖返回信息,浏览器首先从返回头header中查找编码方案标注,如果没有标注,在得知返回内容为html内容的话,将从head的meta标签中读取,如果还没找到,浏览器就不知道如何解码,会消极的选择一种解码方案。

在理论上,推荐html文档在meta中声明编码,且编码的声明一定要在文件开始的1024字节内完成,所以最好在head标签开始时立即声明。


文档中通常都会有一些通过url下载的资源文件,如css和js文件,如果资源文件输出时没有在返回头中指定明确的编码方案,浏览器无法得知编码方案,只能以上面介绍到的文档编码方案来进行解码,这也是浏览器容错的最佳策略。


浏览器根据http头中的ContentType("text/html; charset=GBK"),指定的字符集来解码服务器发送过来的字节流。


我们可以调用 HttpServletResponse.setContentType()设置http头的ContentType。

需要注意的是,URL中的PathInfo和QueryString字符串的编码和解码是由浏览器和应用服务器的配置决定的。我们的程序不能设置,也不要期望用request.setCharacterEncoding()方法能设置URL中参数值解码时的字符集(该方法只针对post)。通常我们也无需关注这个,我们更应该关注消息体的编码解码。


如,可能会在Tomcat中这样配置:

 <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000" URIEncoding="UTF-8" 
               redirectPort="8443" />

【6】开发人员必须清楚的servlet规范

(1) HttpServletRequest.setCharacterEncoding()方法 仅仅只适用于设置post提交的request body的编码而不是设置get方法提交的queryString的编码。

该方法告诉应用服务器应该采用什么编码解析post传过来的内容。

(2) HttpServletRequest.getPathInfo()返回的结果是由Servlet服务器解码(decode)过的。

(3) HttpServletRequest.getRequestURI()返回的字符串没有被Servlet服务器decoded过。

(4) POST提交的数据是作为request body的一部分。

(5) 网页的Http头中ContentType("text/html; charset=GBK")的作用:

  • (a) 告诉浏览器网页中数据是什么编码;
  • (b) 表单提交时,通常浏览器会根据ContentType指定的charset对表单中的数据编码,然后发送给服务器的。

这里需要注意的是:这里所说的ContentType是指http头的ContentType,而不是在网页中meta中的ContentType。

(6) JSP页面 pageEncoding作用

如下所示:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

pageEncoding作用如下:

response.setContentType("text/html; charset=UTF-8");


目录
相关文章
|
4月前
|
存储 监控 安全
如何在Python Web开发中确保应用的安全性?
如何在Python Web开发中确保应用的安全性?
|
10天前
|
中间件 关系型数据库 数据库
docker快速部署OS web中间件 数据库 编程应用
通过Docker,可以轻松地部署操作系统、Web中间件、数据库和编程应用。本文详细介绍了使用Docker部署这些组件的基本步骤和命令,展示了如何通过Docker Compose编排多容器应用。希望本文能帮助开发者更高效地使用Docker进行应用部署和管理。
38 19
|
22天前
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
70 20
|
4月前
|
前端开发 JavaScript
探索现代Web应用的微前端架构
【10月更文挑战第40天】在数字时代的浪潮中,Web应用的发展日益复杂多变。微前端架构作为一种新兴的设计理念,正逐步改变着传统的单一前端开发模式。本文将深入探讨微前端的核心概念、实现原理及其在实际项目中的应用,同时通过一个简单的代码示例,揭示如何将一个庞大的前端工程拆分成小而美的模块,进而提升项目的可维护性、可扩展性和开发效率。
|
2月前
|
Web App开发 编解码 vr&ar
使用Web浏览器访问UE应用的最佳实践
在3D/XR应用开发中,尤其是基于UE(虚幻引擎)开发的高精度场景,传统终端因硬件局限难以流畅运行高帧率、复杂效果的三维应用。实时云渲染技术,将渲染任务转移至云端服务器,降低终端硬件要求,确保用户获得流畅体验。具备弹性扩展、优化传输协议、跨平台支持和安全性等优势,适用于多种终端和场景,特别集成像素流送技术,帮助UE开发者实现低代码上云操作,简化部署流程,保留UE引擎的强大开发能力,确保画面精美且终端轻量化。
116 17
使用Web浏览器访问UE应用的最佳实践
|
4月前
|
监控 安全 测试技术
如何在实际项目中应用Python Web开发的安全测试知识?
如何在实际项目中应用Python Web开发的安全测试知识?
122 61
|
27天前
|
监控 关系型数据库 MySQL
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
31 0
|
3月前
|
弹性计算 Java 关系型数据库
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
|
3月前
|
Kubernetes 安全 Devops
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
108 10
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
|
3月前
|
弹性计算 Java 数据库
Web应用上云经典架构实战
本课程详细介绍了Web应用上云的经典架构实战,涵盖前期准备、配置ALB、创建服务器组和监听、验证ECS公网能力、环境配置(JDK、Maven、Node、Git)、下载并运行若依框架、操作第二台ECS以及验证高可用性。通过具体步骤和命令,帮助学员快速掌握云上部署的全流程。

热门文章

最新文章