设为首页 收藏本站
查看: 356|回复: 0

[经验分享] tomcat参数编码处理过程

[复制链接]

尚未签到

发表于 2017-1-25 10:39:32 | 显示全部楼层 |阅读模式
1. org.apache.coyote.http11.Http11Processor.process
处理请求的数据

 
2. org.apache.coyote.http11.InternalInputBuffer.parseRequestLine()
 
  // 例如:127.0.0.1:8080/test.jsp?a=%E4%B8%AD%E5%9B%BD
        request.unparsedURI().setBytes(buf, start, end - start);
        if (questionPos >= 0) {
         // queryString: a=%E4%B8%AD%E5%9B%BD
            request.queryString().setBytes(buf, questionPos + 1,
                                         end - questionPos - 1);
            // requestURI: 127.0.0.1:8080/test.jsp
            request.requestURI().setBytes(buf, start, questionPos - start);
        } else {
            request.requestURI().setBytes(buf, start, end - start);
        }
 
3. org.apache.catalina.connector.CoyoteAdapter
 
public void service(org.apache.coyote.Request req,
                     org.apache.coyote.Response res)
 
 /**
     * Service method.
     */
    public void service(org.apache.coyote.Request req,
                     org.apache.coyote.Response res)
        throws Exception {
 
        Request request = (Request) req.getNote(ADAPTER_NOTES);
        Response response = (Response) res.getNote(ADAPTER_NOTES);
 
        if (request == null) {
 
            // Create objects
            request = (Request) connector.createRequest();
            request.setCoyoteRequest(req);
            response = (Response) connector.createResponse();
            response.setCoyoteResponse(res);
 
            // Link objects
            request.setResponse(response);
            response.setRequest(request);
 
            // Set as notes
            req.setNote(ADAPTER_NOTES, request);
            res.setNote(ADAPTER_NOTES, response);
 
            // Set query string encoding // 设置了queryString的编码
            req.getParameters().setQueryStringEncoding
                (connector.getURIEncoding());
 
        }
 
        if (connector.getXpoweredBy()) {
            response.addHeader("X-Powered-By", POWERED_BY);
        }
 
    /**
     * Parse additional request parameters.
     */
    protected boolean postParseRequest(org.apache.coyote.Request req,
                                       Request request,
                             org.apache.coyote.Response res,
                                       Response response)
 
3. 解析参数
 
org.apache.catalina.connector.Request.parseParameters
 
 /**
     * Parse request parameters.
     */
    protected void parseParameters() {
 
        parametersParsed = true;
 
        Parameters parameters = coyoteRequest.getParameters();
 
        // getCharacterEncoding() may have been overridden to search for
        // hidden form field containing request encoding
        String enc = getCharacterEncoding();
 
        boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI();
        if (enc != null) {
         // 设置参数的编码
            parameters.setEncoding(enc);
            if (useBodyEncodingForURI) { // 如果此选项设置了的话, 设置queryStr的编码
                parameters.setQueryStringEncoding(enc);
            }
        } else {
            parameters.setEncoding
                (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
            if (useBodyEncodingForURI) {
                parameters.setQueryStringEncoding
                    (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
            }
        }
       
        // 解析query str
        parameters.handleQueryParameters();
 
        if (usingInputStream || usingReader)
            return;
       
        // 不是post, 直接返回
        if (!getMethod().equalsIgnoreCase("POST"))
            return;
 
        String contentType = getContentType();
        if (contentType == null)
            contentType = "";
        int semicolon = contentType.indexOf(';');
        if (semicolon >= 0) {
            contentType = contentType.substring(0, semicolon).trim();
        } else {
            contentType = contentType.trim();
        }
       
        // 当不是表单数据时, 返回
        if (!("application/x-www-form-urlencoded".equals(contentType)))
            return;
       
        // 是表单数据, 读取解析
        int len = getContentLength();
 
        if (len > 0) {
            int maxPostSize = connector.getMaxPostSize();
            if ((maxPostSize > 0) && (len > maxPostSize)) {
                if (context.getLogger().isDebugEnabled()) {
                    context.getLogger().debug(
                            sm.getString("coyoteRequest.postTooLarge"));
                }
                return;
            }
            byte[] formData = null;
            if (len < CACHED_POST_LEN) {
                if (postData == null)
                    postData = new byte[CACHED_POST_LEN];
                formData = postData;
            } else {
                formData = new byte[len];
            }
            try {
                if (readPostBody(formData, len) != len) {
                    return;
                }
            } catch (IOException e) {
                // Client disconnect
                if (context.getLogger().isDebugEnabled()) {
                    context.getLogger().debug(
                            sm.getString("coyoteRequest.parseParameters"), e);
                }
                return;
            }
            parameters.processParameters(formData, 0, len);
        } else if ("chunked".equalsIgnoreCase(
                coyoteRequest.getHeader("transfer-encoding"))) {
            byte[] formData = null;
            try {
                formData = readChunkedPostBody();
            } catch (IOException e) {
                // Client disconnect
                if (context.getLogger().isDebugEnabled()) {
                    context.getLogger().debug(
                            sm.getString("coyoteRequest.parseParameters"), e);
                }
                return;
            }
            if (formData != null) {
                parameters.processParameters(formData, 0, formData.length);
            }
        }
 
    }
 
// 使用querystr的encoding
 public void processParameters( MessageBytes data, String encoding ) {
        if( data==null || data.isNull() || data.getLength() <= 0 ) return;
 
        if( data.getType() == MessageBytes.T_BYTES ) {
            ByteChunk bc=data.getByteChunk();
            processParameters( bc.getBytes(), bc.getOffset(),
                               bc.getLength(), encoding);
        } else {
            if (data.getType()!= MessageBytes.T_CHARS )
                data.toChars();
            CharChunk cc=data.getCharChunk();
            processParameters( cc.getChars(), cc.getOffset(),
                               cc.getLength());
        }
    }
 
小结:
1. 所有参数tomcat都会先做url decode(这很正常, 标准情况下, 都要做url编码, 可同时保证特殊字符的正确传送, 不管get传参还是post传参)
字符 特殊字符的含义 URL编码 
# 用来标志特定的文档位置 %23 
% 对特殊字符进行编码 %25 
& 分隔不同的变量值对 %26 
+ 在变量值中表示空格 %2B 
\ 表示目录路径 %2F 
= 用来连接键和值 %3D 
? 表示查询字符串的开始 %3F
2. 做url编码时, 肯定有指定的字符集(这里假定为utf-8), 如果后端的处理字符集与此字符集不同, 一般来说, 就有乱码
针对get方式的参数,  有两种方式, 可以正确处理
(1) tomcat的服务器配置URIEncoding="UTF-8"
(2) tomcat的服务器配置useBodyEncodingForURI="true", 读取参数之前, 设置
 request.setCharacterEncoding("utf-8");
针对post方式的参数, 只要设置如下即可:
 request.setCharacterEncoding("utf-8");
 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-333216-1-1.html 上篇帖子: tomcat频繁死掉的问题 下篇帖子: Tomcat源码之AprEndpoint
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表