页面树结构
转至元数据结尾
转至元数据起始

(本文档仅供参考)

问题

         本地测试在tomcat 9中测试如下URL链接, 测试串(基于产品自带的例子):http://localhost:8080/smartbi/vision/openresource.jsp?paramsInfo=[{"name":"产品名称参数","value":"汽水","displayValue":"汽水"}]&resid=I4028812115561f6c0144956d0aa20117&showtoolbar=true&refresh=true&user=admin&password=admin 

         发现访问的时候提示“HTTP Status 400 -错误的请求”,不传参打开是正常访问的,这个是为什么?

        

解决方案

       经验证发现是由于tomcat中间件的问题导致,这是Tomcat较新版本默认开启的限制。

        一、Tomcat出现版本

  • 7.0.69+

  • 8.0.39+

  • 8.5.7+

       二、问题原因    

             请求的URL在编码后的中文字符串带反斜杠,这是RFC文档中规定的不安全字符,Tomcat在高版本中增加的安全验证,凡是RFC 3986中非URL可携带的字符,都会返回400错误。

             这个问题根本都还没有进入到业务层就已经被拦截返回了。

          RFC 3986文档关于特殊字符的定义
  • RFC3986文档规定,Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。
  • RFC3986中指定了以下字符为保留字符:
    ! * ' ( ) ; : @ & = + $ , / ? # [ ]
  • 以下为不安全字符
    • 空格 Url在传输的过程,或者用户在排版的过程,或者文本处理程序在处理Url的过程,都有可能引入无关紧要的空格,或者将那些有意义的空格给去掉
    • 引号以及<> 引号和尖括号通常用于在普通文本中起到分隔Url的作用
    • 通常用于表示书签或者锚点

    • % 百分号本身用作对不安全字符进行编码时使用的特殊字符,因此本身需要编码
    • {}|^[]`~ 某一些网关或者传输代理会篡改这些字符

       三、解决办法

             最优解决方案:对于所有服务器传参带特殊符号或者中文的时候必须使用encodeURLComponent 进行编码(在java中对应为 java.net.URLEncoder.encode("...","UTF-8"),但实际中因为不同应用服务器编码不同,有可能使用encodeURLComponent 编码后服务器认为还是存在非法字符,这时候URL传参依然是不生效的,因此是不建议在URL中使用中文,对于带中文的传参建议使用post方式(具体可参考: post方式传参.html)或者Base64编码后传递paramsInfoBase64,具体可参考:《从第三方系统中打开Smartbi资源 》 此文档中的 3、附件参数 部分: 

             

             补充方案:以下方案在部分版本Tomcat可以解决URL带中文和特殊字符传参的问题,如果添加后没有解决,就是这个Tomcat版本不支持这样的方式,请使用【最优解决方案所提供的建议】:

             1)配置tomcat/conf下的catalina.properties(tomcat 9测试发现编码后依然存在问题),添加或者修改:

                    tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}           

                    此修改添加或者修改后一般可以解决传参带特殊符号的问题。

             2)在conf/server.xml设置编码,对于未修改过端口号的server.xml,找到

<Connector port="8080" 和<Connector port="8009",在节点中增加属性URIEncoding="UTF-8",修改后两个节点内容分别是

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

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>,这个方法可以解决传参带中文乱码的问题,但传参带特殊字符的话没有办法处理。

     3)如果上述两步都改了还是会报400等错误,则继续修改server.xml,找到<Connector port="8080" ,增加2个属性:relaxedPathChars="|{}[],"  relaxedQueryChars="|{}[],",加上第二步的修改,该节点内容最终是

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" relaxedPathChars="|{}[]," relaxedQueryChars="|{}[],"/>

注:ie 访问出现400的问题说明

在Tomcat的较高版本,修改了上述补充方案3项配置后,使用ie浏览器直接在地址栏输入未经过encodeURI的带参数地址,如

http://localhost:8080/smartbi/vision/openresource.jsp?paramsInfo=[{"name":"产品名称参数","value":"汽水","displayValue":"汽水"}]&resid=I4028812115561f6c0144956d0aa20117&showtoolbar=true&refresh=true&user=admin&password=admin

仍然会报出400错误,但使用谷歌火狐浏览器则正常,此问题原因参考:https://blog.csdn.net/Mr_JGuo/article/details/109994643 

解决方案参考:

1、js编码encodeURI(encodeURI(URL)),对于上述地址,编码后的url为:

http://localhost:8080/smartbi/vision/openresource.jsp?paramsInfo=[{%22name%22:%22%E4%BA%A7%E5%93%81%E5%90%8D%E7%A7%B0%E5%8F%82%E6%95%B0%22,

%22value%22:%22%E6%B1%BD%E6%B0%B4%22,%22displayValue%22:%22%E6%B1%BD%E6%B0%B4%22}]&resid=I4028812115561f6c0144956d0aa20117

&showtoolbar=true&refresh=true&user=admin&password=admin

2、对于参数中有中文参数名的情况,可以使用以下函数装将中文转成unicode处理

function isChinese(s){
      return /[\u4e00-\u9fa5]/.test(s);
}

function chinese2Unicode(str){
      if(!str){
          return;
      }
      var unicode = '';
      for (var i = 0; i < str.length; i++) {
          var temp = str.charAt(i);
          if(isChinese(temp)){
              unicode += '\\u' + temp.charCodeAt(0).toString(16);
          } else{
              unicode += temp;
          }
      }
      return unicode;
}
然后再使用encodeURIComponent处理,处理后结果如下http://localhost:8080/smartbi/vision/openresource.jsp?resid=I8a8a8c1301759168916803af01759210a68805f3&paramsInfo=%5B%7B%22name%22%3A%22input%22%2C%22value%22%3A%22%5Cu996e%5Cu6599%22%2C%22displayValue%22%3A%22%5Cu996e%5Cu6599%22%7D%5D

Viewtracker License Missing

There is a problem with the license of the Viewtracker addon. Please check if you have a valid license.

授权码细节

评论

  1. 陈晓东 发表:

    目前为止,share.jsp不支持传递openresource.jsp支持的大部分参数,所以以上方案不适用于share.jsp传参失败,建议是替换为openresource.jsp再进行测试。

    share.js支持的是类似设置多语言的设置,例如: l=zh_CN