首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >UTF-8 |表单提交中带有特殊字符的问题| java.io.CharConversionException

UTF-8 |表单提交中带有特殊字符的问题| java.io.CharConversionException
EN

Stack Overflow用户
提问于 2012-12-11 14:16:37
回答 4查看 5.3K关注 0票数 2

我有一个表单,其中有一个文本框和一个提交按钮。我正在使用burp工具更改表单中提交的值,以测试我的服务器端验证。

服务器端验证工作正常,除非有从burp工具输入的%字符,在输入%字符时,服务器显示以下异常。

代码语言:javascript
复制
2012-12-11 11:37:07,860 WARN  [org.apache.tomcat.util.http.Parameters] (ajp-0.0.0.0-8109-19) Parameters: Character decoding failed. Parameter skipped.
java.io.CharConversionException: EOF
                at org.apache.tomcat.util.buf.UDecoder.convert(UDecoder.java:83)
                at org.apache.tomcat.util.buf.UDecoder.convert(UDecoder.java:49)
                at org.apache.tomcat.util.http.Parameters.urlDecode(Parameters.java:429)
                at org.apache.tomcat.util.http.Parameters.processParameters(Parameters.java:412)
                at org.apache.tomcat.util.http.Parameters.processParameters(Parameters.java:363)
                at org.apache.catalina.connector.Request.parseParameters(Request.java:2562)
                at org.apache.catalina.connector.Request.getParameter(Request.java:1060)
                at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:355)
                at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:118)
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
                at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
                at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
                at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
                at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
                at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
                at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:436)
                at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:384)
                at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
                at java.lang.Thread.run(Thread.java:662)

当我提交包含%字符的表单时,它会正确地将其更改为%25,但是我该如何处理此服务器端?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-05-02 23:02:41

其他答案是正确的,因为要求您对输入进行编码是安全的,因为所有浏览器都会这样做,并且理想情况下,您永远不会收到未编码的纯%字符。

但是,话虽如此,如果您仍然坚持看到错误页面,则可以编写一个自定义过滤器来捕获此CharConversionException并向客户机发送错误页面,或者将请求转发到相同的URI,但设置了errorMessage属性,以便以不同的方式处理请求。

这是通过名为useErrorPage的筛选器参数进行配置的。

Tomcat :根据@Santosh共享的源代码,我修改了过滤器,以注入参数验证,并检查所有请求参数,以获得可以通过名为forbiddenChars的过滤器参数配置的禁用字符列表。@Santosh共享的源代码揭示了CharConversionException实际上正在被Tomcat抑制。

将此过滤器放在web.xml中DisplayTag的ResponseOverrideFilter之上,以确保它能拦截所有内容。当涉及到过滤器时,排序可能会产生副作用。

我想借此机会强调一点,Servlet过滤器是一个非常强大的概念,它允许您以任何喜欢的方式对任何请求进行预处理或后处理。大多数web框架(比如MVC的Struts2)都使用过滤器作为它们的入口点。

所以,使用过滤器几乎没有什么不能做的。只需确保您将它们用于正确的目的,就像业务逻辑显然不应该去那里一样,尽管应用程序范围的身份验证可以。

IOException过滤器

代码语言:javascript
复制
public class CharConversionExpFilter implements Filter {

    private char[] forbiddenChars;  // ADDED
    private FilterConfig filterConfig;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
        forbiddenChars = filterConfig.getInitParameter("forbiddenChars")
                               .replace(",", "").toCharArray(); // ADDED
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        String requestURI = ((HttpServletRequest) request).getRequestURI();
        try {
            validateParameters((HttpServletRequest) request);  // ADDED
            chain.doFilter(request, response);
        } catch (IOException e) {
            if (e instanceof CharConversionException) {
                if ("true".equalsIgnoreCase(filterConfig.getInitParameter("useErrorPage"))) {
                    if (response instanceof HttpServletResponse) {
                        ((HttpServletResponse) response).sendError(400,
                        "The request cannot be fulfilled due to bad input.\nError:" + e.getMessage());
                    }
                } else {
                    request.setAttribute("errorMessage", e.getMessage());
                    filterConfig.getServletContext().getRequestDispatcher(requestURI).forward(request, response);
                }
            }
        }
    }

    // ADDED
    private void validateParameters(HttpServletRequest request) throws CharConversionException {
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String parameter = request.getParameter(parameterNames.nextElement());
            if (parameter != null && parameter.length() > 0) {
                for (char forbidChar : forbiddenChars) {
                    if (parameter.indexOf(forbidChar) != -1) {
                        throw new CharConversionException(
                                String.format(
                                        "Parameter: [%s] contains the forbidden character [%c]",
                                        parameter, forbidChar));
                    }
                }
            }
        }
    }

    @Override
    public void destroy() {}
}

web.xml

代码语言:javascript
复制
<filter>
  <filter-name>CharConversionExpFilter</filter-name>
  <filter-class>servlet.filter.CharConversionExpFilter</filter-class>
  <init-param>
    <param-name>useErrorPage</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param> <!-- ADDED -->
    <param-name>forbiddenChars</param-name>
    <param-value>%,*,?,#,$</param-value> <!-- filtering wildcards and EL chars -->
  </init-param>
</filter>

<filter-mapping>
  <filter-name>CharConversionExpFilter</filter-name>
  <url-pattern>/*</url-pattern> <!-- * = ALL; "/servlet-name" if required -->
</filter-mapping>

<error-page>
  <error-code>400</error-code>
  <location>/errorPage.jsp</location> <!-- isErrorPage = true; use "exception" obj -->
</error-page>

希望这篇文章能给你足够的指导,根据你的需要找出解决方案。( Java :语法突出显示错误地将<url-pattern>/*解释为多行注释的开始。请忽略它。)

票数 0
EN

Stack Overflow用户

发布于 2013-04-26 19:15:09

您遇到的问题是,解码器在以%符号开头时需要一个有效的、可解码的参数。提交表单时,输入参数%被正确编码为%25,当您使用Burp编辑此请求时,据我所知,这种编码不会发生。Burp很乐意向您的服务器发送%符号,您的服务器端验证假定这是编码值的开始,但解码失败,因为它基本上是一个损坏的参数。

我最好的猜测是不要只发送%-values (即不伴随数字值)。这就像在一个空的reference..some上调用一个方法一样,事情就是不起作用。我建议您尝试检查百分比符号是否被您自己的输入验证批准或拒绝,但只要它首先经过解码,它就必须进行编码。

票数 1
EN

Stack Overflow用户

发布于 2013-04-29 15:32:06

使用此测试(在应该是URL编码的数据中包含一个原始'%‘),您正在测试您的应用程序是否适当地拒绝了格式错误的输入。这没什么错。

如果你想使用burp推送数据,你需要对它进行编码,这意味着你需要在你想要的地方放入'%25‘。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13814700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档