zoukankan      html  css  js  c++  java
  • postman 接口参数里面有+或特殊符号处理办法

    问题背景
    接收客户端传入参数,base64解码失败,经过排查发现原因是参数上传前字符串中有+,但是PHP接收后,发现+变成了空格,导致base64解码失败。
    
    测试验证
    访问一个测试的接口 /internal/test
    
    curl 'http://127.0.0.1/internal/test?a=abc+def'
    1
    验证1:
    简单输出$_GET
    
    public function test() {
       var_dump($_GET);
    }
    1
    2
    3
    结果:
    
    array(1) {
      ["a"]=>
      string(7) "abc def"
    }
    1
    2
    3
    4
    结论:可以看到直接接收GET参数,+变成了空格
    
    +变成空格的原因
    经过一顿查资料,首先我们要知道URL编码是什么
    
    URL编码
    一个例子
    我们常见的一个URL,例如CSDN搜索功能的一个URL(https://so.csdn.net/so/search/s.do?q=PHP基于字典树算法实现搜索联想功能&t=&u=),当你从浏览器中复制出来的时候,这个URL长下面这样子 https://so.csdn.net/so/search/s.do?q=PHP%E5%9F%BA%E4%BA%8E%E5%AD%97%E5%85%B8%E6%A0%91%E7%AE%97%E6%B3%95%E5%AE%9E%E7%8E%B0%E6%90%9C%E7%B4%A2%E8%81%94%E6%83%B3%E5%8A%9F%E8%83%BD&t=&u=
    
    这就是URL被编码了,这里编码是将中文转换成了%开头的两个十六进制数。
    
    为什么URL会被编码呢?
    URL中的参数部分是由一个个key=value的参数对组成,而如果&=/?等在URL具有一定功能的特殊字符出现在key或者value中时,就会导致语义出现不一致的情况,例如参数q的值是a&b,那么当出现q=a&b&f=s这样一个参数对时,是表示q的值是a&b,还是q的值是a,而b的值为空呢?
    
    因此需要对URL进行编码,这样被编码过的字符就不再会有歧义,上面例子中的q=a&b&f=s会被编码成q=a%26b&f=s,你看这样是不是就不会混乱了。
    
    如何对URL进行编码呢?
    URL如何进行编码由RFC标准进行规定,
    
    在RFC-1738对URL进行说明的各项标准中,提出了要对URL中不安全的字符进行编码,编码方式即使用%和紧跟的两个十六进制数字表示,注意在该标准中空格被编码成+
    在升级版RFC-2396对URI进行说明的各项标准中,再次提到了对参数进行编码,注意在在该标准中空格被编码成%20
    在再次升级版的RFC-3986标准中,对Url的编解码问题做出了更加详细的建议,指出了哪些字符需要被编码才不会引起Url语义的转变,以及对为什么这些字符需要编码做出了相应的解释。
    回头来研究下一开始的问题
    通过以上的资料,我们可以看出来+被变成了空格的原因,正是按照RFC-1738标准进行的反编码,也就是.PHP接收$_GET参数遵循的是的是RFC-1738标准。
    所以直接读取$_GET时,+就反过来被解码成了空格
    
    怎么解决这个问题
    那我们怎么让PHP不按照RFC-1738标准进行解码,而是按照升级版的RFC-3986标准进行解码呢?
    
    最简单的办法当然是让+以正确的方式进行编码,也就是在客户端请求接口时,按照RFC-3986标准进行对URL进行编码。此时+被编码成%2b,当PHP接收参数时,将%2b解码成+,大功告成。
    
    验证结果
    对URL进行正确的编码
    
     curl 'http://127.0.0.1/internal/test?a=abc%2bdef' 
    1
    此时可以看到接口输出
    
    array(1) {
      ["a"]=>
      string(7) "abc+def"
    }
    
    1
    2
    3
    4
    5
    PHP语言里还有别的坑吗?
    除了接收$_GET参数外,PHP中还有对URL参数处理的两个常用的函数urlencode和urldecode。
    注意这两个函数也是遵循RFC-1738进行编码和解码,从官网的说明可以看到
    
    This differs from the » RFC 3986 encoding (see rawurlencode()) in that for historical reasons, spaces are encoded as plus (+) signs.
    
    做个试验
    先对字符串abc def进行编码
    
     $str = 'abc def';
     echo urlencode($str);
    1
    2
    输出结果
    
    abc+def
    1
    然后对字符串a=abc+def进行解码
    
     $str = 'a=abc+def';
     echo urldecode($str);
    1
    2
    输出结果
    
    a=abc def
    1
    可以看出确实空格被编码成了+,而+则被解码成空格
    
    怎么解决呢?
    那PHP里面有没有使用RFC-3986标准进行编码的呢,有的,是rawurlencode和rawurldecode,PHP官方是这么写的
    
    rawurlencode — URL-encode according to RFC 3986
    
    再来做个试验
    先对字符串abc def进行编码
    
     $str = 'abc def';
     echo rawurlencode($str);
    1
    2
    输出结果
    
    abc%20def
    1
    可以看到空格被编码成%20,然后对字符串a=abc+def进行解码
    
     $str = 'a=abc+def';
     echo rawurldecode($str);
    1
    2
    输出结果
    
    a=abc+def
    1
    可以看到+解码后还是+,没有变成空格
    
    结论
    所以最符合标准,并且比较容易实现的方案就是让客户端or前端在请求服务端接口时遵循RFC-3986标准进行正确的URL编码
  • 相关阅读:
    虚函数中的变量作用域问题
    C++技能重拾2
    C++技能重拾
    位运算取第一个非0的位 r & (~(r-1))
    ThoughtWorks微服务架构交流心得
    字符串匹配的sunday算法
    Codeforces Round #270(利用prim算法)
    HDFS建筑与shell操作
    Spark SQL 源代码分析系列
    HDU 4686 Arc of Dream(递归矩阵加速)
  • 原文地址:https://www.cnblogs.com/kevin-yang123/p/14469720.html
Copyright © 2011-2022 走看看