SpringBoot内嵌Tomcat,解决处理非法字符参数问题

问题出现的环境背景及自己尝试过哪些方法

Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后,添加了对于http头的验证。

具体来说,就是添加了些规则去限制HTTP头的规范性。

org.apache.tomcat.util.http.parser.HttpParser#IS_NOT_REQUEST_TARGET[]中定义了一堆not request target

if(IS_CONTROL[i] || i > 127 || i == 32 || i == 34 || i == 35 || i == 60 || i == 62 || i == 92 || i == 94 || i == 96 || i == 123 || i == 124 || i == 125) {
                IS_NOT_REQUEST_TARGET[i] = true;
            }

不太想用POST,又由于是内嵌的Tomcat,所以为了开发方便还是想通过修改springboot配置的方式去解决,
刚看了下 server.tomcat.* 相关的配置,暂时没有找到解决非法字符的问题### 问题描述

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)
<parent>

    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <!--<version>1.5.14.RELEASE</version>-->
    <version>2.0.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

你期待的结果是什么?实际看到的错误信息又是什么?

请求URL:http://localhost/xxx/中文参数

报错:java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986

很多人给了解决办法,但是还是感觉不太灵活,还是想通过springboot配置的方式,

阅读 11.1k
2 个回答

对这个“中文参数”编码即可。

对于get请求
如果你的请求是get,参数有中文的,比如 ?name=张上,按照如下处理
前端使用 encodeURIComponent(encodeURIComponent(url)),对url进行二次编码。
后端:拿到参数值,使用URLDecoder.decode(s, "UTF-8")解码一下。这样方式确实可行的,答主在实际项目总使用过。
举个例子吧:
前端:

<script type="text/javascript">
   var url = "/xxx/param/test";
     
     var name = "张上";
     
     name = encodeURIComponent(name);
     name = encodeURIComponent(name);//二次编码
     alert(name);
     url = url + "?name="+name;
     window.location.href = url;
     </script>

后端:

@Controller
@RequestMapping(value="/param")
public class ParamController extends BaseController<ParamEntity> {
    /**
     * @throws UnsupportedEncodingException 
     * 
     */
    @RequestMapping(value="/test",method=RequestMethod.GET)
    public String test(@RequestParam("name") String name) throws UnsupportedEncodingException{
        name = URLDecoder.decode(name, "UTF-8");//实测,可以正确的得到中文。
        System.out.println(name);
        return "index";
    }
}

注意:get请求有中文参数,可以指定容器使用何种编码规则来解码提交的参数(有人回答使用这种方式,即修改tomcat 配置文件中的Connector中的URIEncoding参数),但是这种做法不建议使用,推荐使用二次编码吧。
为什么需要二次编码?可以看如下博文:
eURIComponent编码2次

新手上路,请多包涵

springboot 2.0 之后的版本

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

/**
 * Created on 2019/2/18 17:41.
 *
 * @author Ethan
 * <p>
 * java.lang.IllegalArgumentException:
 *  Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986.
 * </p>
 */
@Component
public class PortalTomcatWebServerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.addConnectorCustomizers(connector -> connector.setAttribute("relaxedQueryChars", "{}[]|"));
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题