- 浏览: 542074 次
- 性别:
- 来自: 天津
文章分类
- 全部博客 (230)
- java (87)
- c/c++/c# (39)
- ASP.net MVC (4)
- eclipse/visual studio (3)
- tomcat/weblogic/jetty (13)
- linux/unix/windows (20)
- html/javascript/jquery/kendo/bootstrap/layui/vue/react (31)
- hibernate/struts/spring/mybatis/springboot (21)
- lucene/solr/ELK (2)
- shiro (0)
- oracle/sqlserver/mysql/postgresql (23)
- shell/python/ruby (6)
- android (0)
- maven/ant (1)
- freemarker/thymeleaf/velocity (1)
- open source project (41)
- cache/memcached/redis (0)
- nosql/hadoop/hbase/mongodb (0)
- system architecture/dubbo/zookeeper (0)
- software testing (0)
- system optimization (0)
- system security (0)
- tcp/udp/http (2)
- roller/wordpress (2)
- 工具收藏 (8)
- 文摘 (4)
- 生活 (0)
最新评论
-
coconut_zhang:
这个demo 非常完整了,是指下面说的那个html 模版,模版 ...
flying sauser, thymeleaf实现PDF文件下载 -
a93456:
你好,你有完整的demo吗? String template这 ...
flying sauser, thymeleaf实现PDF文件下载 -
yujiaao:
fn 函数循环是没有必要的啊,可以改成
protecte ...
Java 笛卡尔积算法的简单实现 -
安静听歌:
设置了.setUseTemporaryFileDuringWr ...
使用jxl导出大数据量EXCEL时内存溢出的解决办法 -
q280499693:
写的很详细,但是我现在想知道他们是怎么定位log4j.prop ...
关于SLF4J结合Log4j使用时日志输出与指定的log4j.properties不同
1.urlencode和decode
字符的编码和解码在有中文和特殊符号的情况下,常常是一个头疼的问题。url的encode和decode是解决这个问题的一个分支,通过简单的算法将特殊字符编码,其大致算法如下:
- The alphanumeric characters “a” through “z”, “A” through “Z” and “0″ through “9″ remain the same.
- The special characters “.”, “-”, “*”, and “_” remain the same.
- The space character ” ” is converted into a plus sign “+”.
- All other characters are unsafe and are first converted into one or more bytes using some encoding scheme. Then each byte is represented by the 3-character string “%xy”, where xy is the two-digit hexadecimal representation of the byte. The recommended encoding scheme to use is UTF-8. However, for compatibility reasons, if an encoding is not specified, then the default encoding of the platform is used。
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < s.length();) {
- int c = (int) s.charAt(i);
- if (c == ' ') {
- sb.append('+');
- }else if( c == '%') {
- sb.append("%25");
- }else if(c 符合前面第4条的描述,是特殊字符){
- byte[] ba = str.getBytes(charset);
- for (int j = 0; j < ba.length; j++) {
- String ts = Integer.toHexString(b)取后两位;
- sb.append("%").append(ts);
- }
- }else {
- sb.append(c);
- }
- }
- String result = sb.toString();
StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length();) { int c = (int) s.charAt(i); if (c == ' ') { sb.append('+'); }else if( c == '%') { sb.append("%25"); }else if(c 符合前面第4条的描述,是特殊字符){ byte[] ba = str.getBytes(charset); for (int j = 0; j < ba.length; j++) { String ts = Integer.toHexString(b)取后两位; sb.append("%").append(ts); } }else { sb.append(c); } } String result = sb.toString();
通过这样的方式,比如 “a中国” 就会变成”a%E4%B8%AD%E5%9B%BD”,在发送端编码,在接受方使用相反的算法解码即可。但是这里面的几个特殊字符,比如%,常常会带来一些隐晦的问题。
2. 问题一:apache的rewrite
在做统一域名迁移的时候,遇到了一例这样的问题,现象是以前传递过来的一个正确参数现在超长了,排查后发现,由于为了兼容两个域名,我们对于某些url做了一个rewrite,而apache的rewrite模块默认会对%这样的字符转换为%25,再发送rewrite的响应到浏览器,因此,参数就由%252BeNh变成了%25252BeNh,导致超长了。
解决办法,修改apache的rewrite参数,添加一个NE, 如下:
RewriteRule ^/martini/(.*)$ /eve/$1 [L,R,NE]
1 |
RewriteRule ^/martini/(.*)$ /eve/$1 [L,R,NE] |
问题得到解决,更多apache的rewrite配置可以参考:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html
. 问题二:容器的自动decode
在eve的tracelog模块中,会将目标url作为一个参数,经过UrlEncoder.encode后,包装到eve的url中,然后发送邮件给客户,这样客户点击时,就可以从eve进行跳转,从而记录下相关访问数据。如目标url为http://www.taobao.com,包装后变成http://eve.alibaba.com/dispatch?targetUrl=http%3A%2F%2Fwww.taobao.com&logid=12345.
但是在遇到了一次问题,当目标url本身也有参数,而且是经过编码的中文参数的时候,就出现了问题。eve的使用方先用gbk字符将目标url编码成了如下样式:
http://www.taobao.com?user=%EE%E2
然后eve像平常一样,将这个url用utf-8再次encode,拼装得到url如下:
结果,客户点击跳转链接,出错了。
在eve的跳转处理servlet中,大概处理逻辑是如下:
- String url = req.getParameter(TracelogDto.TARGET_URL);
- url = URLDecoder.decode(url, "utf-8");
String url = req.getParameter(TracelogDto.TARGET_URL); url = URLDecoder.decode(url, "utf-8");
理想情况下处理出来的url是http://www.taobao.com?user=%EE%E2
实际却是:http://www.taobao.com?user=?
开始怀疑是apache转发的问题,后来排查发现是jboss的req.getParameter()时,对该参数已经进行了一次decode了,所以照成这个问题。之后查了一下代码,发现tomcat和jetty都在getParameter时都做了这个事情,找了下servlet规范和相关java的接口,没有明确规定在.getParameter时需要先decode,网上倒是有文章说,但事实上,主流容器都做了这个事情。
- 目前request经过解析了的方法有:parsePostData(int, ServletInputStream),parseQueryString(String),getContextPath(),
- getPathInfo()没有解析的方法有:getRequestURI()
因此,最终的解决方案是去掉跳转代码中的decode就可以了,这本来是一个很简单的问题,但因为不知道容器做了一次decode,而带来了一些困扰。
附:
jetty的getParameter decode的调用流程:
1 2 3 4 |
--UrlEncoded.decodeUtf8To(..); --org.eclipse.jetty.http.HttpURI.decodeQueryTo(MultiMap parameters) --org.eclipse.jetty.server.Request. extractParameters() --org.eclipse.jetty.server.Request.getParameter(String name) |
tomcat的getParameter decode的调用流程:
1 2 3 4 5 6 7 |
--org.apache.tomcat.util.http.Parameters.urlDecode --org.apache.tomcat.util.http.Parameters.processParameters --org.apache.tomcat.util.http.Parameters.handleQueryParameters --org.apache.catalina.connector.Request.handleQueryParameters --org.apache.catalina.connector.Request.parseParameters --org.apache.catalina.connector.Request.getParameter(String name) --org.apache.catalina.connector.RequestFacade.getParameter(String name) |
另外,encode和decode都需要指定一个字符集,如果UTF-8,GBK,或者ISO-8859-1,tomcat在不指定的情况下,queryString和body都是用ISO-8859-1来做decode的。
2. 容器的编码问题
对于tomcat在getParameter时的字符处理,代码如下:
- String enc = getCharacterEncoding();
- boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI();
- if (enc != null) {
- parameters.setEncoding(enc);
- if (useBodyEncodingForURI) {
- parameters.setQueryStringEncoding(enc);
- }
- } else {
- parameters.setEncoding (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
- if (useBodyEncodingForURI) {
- parameters.setQueryStringEncoding
- (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
- }
- }
String enc = getCharacterEncoding(); boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI(); if (enc != null) { parameters.setEncoding(enc); if (useBodyEncodingForURI) { parameters.setQueryStringEncoding(enc); } } else { parameters.setEncoding (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); if (useBodyEncodingForURI) { parameters.setQueryStringEncoding (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING); } }
该段代码表明,如果设置了request的(可以通过在filter中设置request.setCharacterEncoding(charset),或者在http头中设置Content-type: application/x-www-form-urlencoded; charset=UTF-8;那么就用指定的编码解析请求body中的paramter。
如果之前响应到浏览器的HTML代码里有类似<meta http-equiv=”Content-Type” content=”text/html; charset=GBK” />,那么此HTML的form表单将以html指定的的编码方式提交数据(但注意,ie虽然以这个编码,但是并不将Content-type: application/x-www-form-urlencoded; charset=UTF-8 这个charset设置上去,所以在容器中request.getCharacterEncoding()是null的。事实上,我们的LocaleFilter就是解决这个问题。)则body的解码使用对应的charset。
对于QueryString是否使用,还要看看useBodyEncodingForURI的设置.这个设置是由connector来设置的,也就是容器的配置,不是每次请求可以变的,如果没有设置,queryString就会以ISO-8859-1的方式来解码(包括urldecode)。
对于浏览器来说,queryStirng如果是在window下,ie就以GBK编码传输,firefox以GBK编码做urlEncode后传输。
然后对于容器来说,一般还有一个URIencoding可以设置,是控制整个uri的编码方式的
3. jetty的处理
1.url的处理
jetty对于url和querystr,在每个HttpConnection初始化的时候,有如下代码
- _uri = StringUtil.__UTF8.equals(URIUtil.__CHARSET)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
_uri = StringUtil.__UTF8.equals(URIUtil.__CHARSET)?new HttpURI():new EncodedHttpURI(URIUtil.__CHARSET);
在URIUtil中:
- final String __CHARSET=System.getProperty("org.eclipse.jetty.util.URI.charset",StringUtil.__UTF8);
final String __CHARSET=System.getProperty("org.eclipse.jetty.util.URI.charset",StringUtil.__UTF8);
因此我们可以看到,对于url,默认使用UTF-8处理,如果设置了org.eclipse.jetty.util.URI.charset,就用设置的字符编码处理。
2.querystr的处理
先看代码
- if (_uri!=null && _uri.hasQuery())
- {
- if (_queryEncoding==null)
- _uri.decodeQueryTo(_baseParameters);
- else
- {
- _uri.decodeQueryTo(_baseParameters,_queryEncoding);
- }
- }
if (_uri!=null && _uri.hasQuery()) { if (_queryEncoding==null) _uri.decodeQueryTo(_baseParameters); else { _uri.decodeQueryTo(_baseParameters,_queryEncoding); } }
可以看到,如果设置了queryEncoding,就会按照设置的编码来解析,在Request中,有方法
publicvoid setQueryEncoding(String queryEncoding);
也可以通过request.setAttribute来设置
- publicvoid setAttribute(String name, Object value) {
- if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name))
- setQueryEncoding(value==null?null:value.toString());
- }
publicvoid setAttribute(String name, Object value) { if ("org.eclipse.jetty.server.Request.queryEncoding".equals(name)) setQueryEncoding(value==null?null:value.toString()); }
如果没有设置queryEncoding,会是什么情况呢?
在EncodedHttpUri中,有如下代码
- public void decodeQueryTo(MultiMap parameters)
- {
- if (_query==_fragment)
- return;
- UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,_encoding),parameters,_encoding);
- }
public void decodeQueryTo(MultiMap parameters) { if (_query==_fragment) return; UrlEncoded.decodeTo(StringUtil.toString(_raw,_query+1,_fragment-_query-1,_encoding),parameters,_encoding); }
可以看到,会使用_encoding参数,这个就是前面new出EncdodeHttpUri的传入参数,即org.eclipse.jetty.util.URI.charset设置的参数。
因此,对于queryStr,如果请求中设置了_queryEncoding,就用他的编码,否则用系统参数org.eclipse.jetty.util.URI.charset设置的编码,否则用默认编码UTF-8
3.body部分
默认使用 UTF-8 编码,当然可以在使用之前使用 request.set CharacterEncoding 设定编码.
注:网上有资料说POST 参数默认使用 Content-type 中的 Charset 编码,但看了下源码,tomcat是有这个功能的,在getCharacterEncoding的时候,有一个如果为null则去ContentType中取的动作,但jetty好像没有)
发表评论
-
easypoi 按照模板到出excel并合并单元格
2022-11-10 21:46 145这是entity类,注解的mergeVertical是纵向合 ... -
Java时区处理之Date,Calendar,TimeZone,SimpleDateFormat
2017-03-31 14:59 1361一、概述 1、问题描述 使用Java处 ... -
jxls操作excel文件
2017-03-03 14:51 1094JXLS是基于Jakarta POI API的Excel报表 ... -
jquery formValidator 表单验证插件, ajax无法传值到后台问题的解决
2016-06-24 17:10 662data : { count: Math.random ... -
thymeleaf与spring整合
2016-06-15 10:08 12341、使用的是Spring EL而不是Ognl。2、访问上下文 ... -
SpringMVC 400 Bad Request 问题
2016-06-15 09:11 1964在提交表单时,发生400错误,并未进入save方法。 ... -
bootstrap3自定义popover显示的内容
2016-05-27 11:14 1143<script type="text/jav ... -
keytool生成证书与Tomcat SSL配置
2016-05-18 13:29 791一、Keytool介绍 Keytool是一个Java数据证书的 ... -
eclipse插件Maven添加依赖查询无结果的解决方法(Select Dependency doesn't work)
2016-04-22 08:33 735在eclipse中用过maven的可能都遇到过这种情况,我 ... -
JS 中面向对象的5种写法
2015-08-13 15:54 705定义Circle类,拥有成员变量r,常量PI和计算面积的成员 ... -
动态载入/删除/更新外部 JavaScript/Css 文件的代码
2015-07-31 15:09 4117动态载入 JavaScript/Csss 文件 传统加载外部 ... -
Java_Ant详解
2015-06-15 16:54 7271,什么是antant是构建工 ... -
httpClient通过代理(Http Proxy)进行请求
2014-09-16 14:18 1226httpClient通过代理(Http Proxy)进行请求 ... -
httpclient上传文件及传参数
2014-09-16 11:07 11634用到的包有commons-httpclient-3.0.1. ... -
简单返回顶部代码及注释说明
2014-07-16 10:44 966最近做了一个排行榜页 ... -
深入浅出JSONP:解决AJAX跨域问题
2014-04-16 11:00 811取不到数据! 上周客户新买了服务器,原本在旧的服务器上放着 ... -
Progress Bar Plugin
2013-12-26 10:04 825from: http://digitalbush.com/p ... -
javascript cookie
2013-11-08 09:18 1061cookie概述在上一节, ... -
Java文件下载的几种方式
2013-08-19 14:15 874public HttpServletResponse dow ... -
http上传文件深度解析-高性能http传输
2013-07-23 10:41 9768最近在做web服务器的时候将一些应用集成在了服务器里面,比 ...
相关推荐
网址编码解码,jQuery版Url.encode,Url.decode,Url.parse,一个来自jQuery的URL Decoder解码、编码插件,为你的URL安全定义一道安全防线,示例文件本身就是一个值得学习的实例,自带的示例将告诉你如何使用这款URL...
为了解决这个问题,URL编码(URL encode)和解码(URL decode)机制应运而生。这个压缩包文件"URL encode 与 URL decode 的C语言实现.zip"显然提供了用C语言编写的函数,用于对URL进行编码和解码操作。 URL编码是一...
`Encode_ Decode Tools`是一款用于URL编码和解码的工具,它可以帮助开发者和用户方便地处理这些编码问题。这款工具可能提供了简单的用户界面,允许用户输入URL或字符串,然后点击按钮进行编码或解码操作。它支持对...
标题中的“java net unicode / native2ascii / url decode / url encode / UTF8 / js url code”涉及了Java网络编程中的几个关键概念,这些概念在处理字符编码时非常重要。以下是对这些概念的详细解释: 1. **...
自己动手写了一个HTML码URL-encode码转换器,给大家分享一下。
【渝海URL编码转换工具 v1.1_yh_url_encode】是一个专用于处理URL编码问题的实用工具。在互联网通信中,URL(统一资源定位符)是用于标识资源的字符串,它包含网络协议、主机名、路径、查询参数等部分。然而,URL中...
除了HtmlEncode与HtmlDecode外,文中还提到了`UrlEncode`和`UrlDecode`的概念。这两个操作主要用于处理URL中的特殊字符,确保URL能够被正确解析并传输。 **UrlEncode**的目的是将URL中的特殊字符转换为对应的百分比...
hexencode 将字符串指定字符集进行编码成16进制字符串 hexstring 将字符串指定字符集进行编码成16进制字符串 power 求数字的幂函数 replace 将指定字符串中的源字符替换为目标字符 todec 将指定进制的数字转换成10...
在标题提到的“JavaScript的URL encode decode源代码,ip验证,TRim”中,我们将探讨这三个关键概念。 1. URL编码与解码: 在JavaScript中,我们经常需要对URL中的特殊字符进行编码,以确保它们在HTTP请求中被正确...
2. URL编码:URL编码(又称百分号编码)是为了解决URL中不能包含某些特殊字符的问题,它将非字母数字字符转换为“%”加两位十六进制数的形式。 3. Hex编码:Hex编码是将每个字节转换为两个16进制数字的表示,便于...
C++的UrlEncode UrlDecode代码。
在做一个公告浏览功能时,只要通过url传递的某参数值中包含 & 或 ,就会出现问题–该变量的值无法显示。 问题定位结果: 遇到&时,该参数的值会自动截断,导致参数值传递有误。 二、问题的解决 java代码中做如下...
使用这个库可以很方便的编码解码URLCode。里面带了ESP8266看门狗开关,可以在调用这个库之前宏定义ESP8266就可以开启库的看门狗设置。避免触发看门狗。建议配合我主页的教程一起食用。哪怕是小白也可以轻松使用。
EnCode/DeCode转换工具是一款专门针对这一需求设计的小巧实用软件,它能够处理ANSI和UTF-8这两种常见的字符编码格式,帮助开发者解决字符转换的问题。 首先,我们要理解编码与解码的基本概念。编码是将可读的文本...
linux系统c++实现的url和base64编解码 在webserver中会使用 自己实现的一个webserver,详见https://download.csdn.net/download/k117470154/10234299
字符串转EnCode_c# 字符串转EnCode_c# 字符串转EnCode_c# 字符串转EnCode_c# 字符串转EnCode_c# 字符串转EnCode_c# 字符串转EnCode_c# 字符串转EnCode_c#
`URLEncoder.encode()` 和 `URLDecoder.decode()` 是Java标准库中的两个关键方法,分别用于对URL参数进行编码和解码,以确保数据能够正确无误地在网络间传输。 **`URLEncoder.encode()`** 方法接受两个参数:需要...
在Java中,可以使用`java.net.URLEncoder.encode()`方法对加密字符串进行编码,解码则使用`java.net.URLDecoder.decode()`。 7. **异常处理**:在实际应用中,应更全面地处理可能抛出的异常,包括捕获并记录异常...
在这个例子中,`URLEncoder.encode()`用于URL编码,`StringEscapeUtils.escapeHtml4()`用于HTML转义,然后分别有对应的解码和unescape方法。运行这段代码,你会看到原始字符串如何经过编码和转义,以及如何恢复到...
这是因为URL中包含的某些字符可能会导致解析问题或错误。在本文中,我们将深入探讨JavaScript中用于URL编码的主要方法——`encodeURIComponent()`函数,并通过实例来理解其用法。 `encodeURIComponent()`函数是...