zoukankan      html  css  js  c++  java
  • Http请求传输base64码+号变空格问题

    Http请求传输base64码+号变空格问题

    Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。
    Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。采用Base64编码具有不可读性,需要解码后才能阅读。
    Base64由于以上优点被广泛应用于计算机的各个领域,然而由于输出内容中包括两个以上“符号类”字符(+, /, =),不同的应用场景又分别研制了Base64的各种“变种”。为统一和规范化Base64的输出,Base62x被视为无符号化的改进版本。(by百度百科)

    一、简单Http Get请求参数带+示例

    Base64中,加号(+)是Base64编码的一部分,如果将+号转变为空格,就会导致解密失败。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script type="text/javascript">
            function toSend() {
                location.href="http://localhost:8080/sendHttp?str=123+456";
            }
            function toSend2() {
                location.href="http://localhost:8080/sendHttp?str="+encodeURIComponent("123+456");
            }
        </script>
    </head>
    <body>
        <a href="###" onclick="toSend()">模拟请求</a> 
        <a href="###" onclick="toSend2()">转码模拟请求</a>
    </body>
    </html>
    

    后台处理:

    package com.example.demo.web;
    
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * @Description Http传输base64编码 加号变空格问题
     * @Author jie.zhao
     * @Date 2019/9/16 9:58
     */
    @RestController
    public class HttpBase64Controller {
    
        @GetMapping("/sendHttp")
        public String sendHttp(String str){
            System.out.println(str);
            return str;
        }
    }
    

    模拟请求:str 参数为:123+456

    浏览器地址: http://localhost:8080/sendHttp?str=123+456
    后台接收值:123 456

    通过模拟请求可以看出,当我们在URL中传递参数中带有+时,会被转换成空格导致后台获取的参数不正确。

    解决方案一:

    通过 encodeURIComponent 对请求参数进行转码

    转码模拟请求: str 参数为:123+456

    浏览器地址: http://localhost:8080/sendHttp?str=123%2B456
    后台接收值:123+456

    解决方案二:

    改为form表单提交

    二、RestAPI接口Http Get请求参数带+示例

    RestTemplate是Spring Web模块提供的一个基于Rest规范提供Http请求的工具。应用中如果需要访问第三方提供的Rest接口,使用RestTemplate操作将非常方便。

    配置如下:

    package com.example.demo.conf;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * @Description RestTemplateConfig配置
     * @Author jie.zhao
     * @Date 2019/9/16 11:31
     */
    @Configuration
    public class RestTemplateConfig {
        @Bean
        public RestTemplate restTemplate( ) {
            return new RestTemplate();
        }
    }
    

    后台处理:

    package com.example.demo.web;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    
    /**
     * @Description Http传输base64编码 加号变空格问题
     * @Author jie.zhao
     * @Date 2019/9/16 9:58
     */
    @RestController
    public class HttpBase64Controller {
    
        @Autowired
        RestTemplate restTemplate;
    
        @GetMapping("/apiSend")
        public String apiSend(String str) {
            String result = restTemplate.getForObject("http://localhost:8080/apiReceive?str=" + str, String.class);
            return result;
        }
    
        @GetMapping("/apiReceive")
        public String apiReceive(String str) {
            System.out.println(str);
            return "接收参数" + str;
        }
        
        @GetMapping("/apiSend2")
        public String apiSend(String str) {
            str = URLEncoder.encode(str, "UTF-8");
            System.out.println("URL编码:" + str);
            String result = restTemplate.getForObject("http://localhost:8080/apiReceive?str=" + str, String.class);
            return result;
        }
    
        @GetMapping("/apiReceive2")
        public String apiReceive(String str) {
            str = URLEncoder.encode(str, "UTF-8");
            System.out.println("URL编码:" + str);
            System.out.println(str);
            return "接收参数" + str;
        }
    }
    

    模拟请求:str 参数为:123+456

    浏览器地址: http://localhost:8080/apiSend?str=123+456
    后台接收值: 123 456

    通过模拟请求可以看出,当我们在请求接口参数中带+,也会被处理成空格导致后台获取的参数不正确。

    解决方案一:

    参数明确有可能有+号并且不可能有空格的时候,直接replaceAll(" ", "+")。

    解决方案二:

    对参数进行URL编码,URLEncoder.encode(str)。

    模拟请求:str 参数为:123+456

    浏览器地址: http://localhost:8080/apiSend?str=123+456
    后台接收值: 123+456

    注意: 存在的问题 URLEncoder会把空格转成+

    模拟请求:str 参数为:123 456

    浏览器地址: http://localhost:8080/apiSend?str=123 456
    后台接收值: 123+456

    三、GET请求会把+号转为空格的原因

    1、RFC2396

    RFC2396 列明了";" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," 这些字符为保留字符,需要转译后才能出现在uri中。

    2.2. Reserved Characters
    
    Many URI include components consisting of or delimited by, certain
    special characters.  These characters are called "reserved", since
    their usage within the URI component is limited to their reserved
    purpose.  If the data for a URI component would conflict with the
    reserved purpose, then the conflicting data must be escaped before
    forming the URI.
    
      reserved    = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
                    "$" | ","
    
    The "reserved" syntax class above refers to those characters that are
    allowed within a URI, but which may not be allowed within a
    particular component of the generic URI syntax; they are used as
    delimiters of the components described in Section 3.
    
    2、RFC1866

    RFC1866 规定所有表单的默认编码为application/x-www-form-urlencoded。

    RFC 1866            Hypertext Markup Language - 2.0        November 1995
    
    To process a form whose action URL is an HTTP URL and whose method is
    `GET', the user agent starts with the action URI and appends a `?'
    and the form data set, in `application/x-www-form-urlencoded' format
    as above. The user agent then traverses the link to this URI just as
    if it were an anchor (see 7.2, "Activation of Hyperlinks").
    
    NOTE - The URL encoding may result in very long URIs, which cause
    some historical HTTP server implementations to exhibit defective
    behavior. As a result, some HTML forms are written using
    `METHOD=POST' even though the form submission has no side-effects.
    

    简单的讲就是form表单提交,from表单提交会默认对参数进行encode操作。浏览器会对form表单的数据进行url编码,把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。

    如果表单有加号(+),url编码后会变为%2,这时后接收数据后,对参数解码后转变为+号如果表单有空格,url编码后会变为+,后台接收数据化,解码变为空格。

    如果是用的程序写的http请求,需要加一个请求头Content-Type:application/x-www-form-urlencoded,这样就会对参数进行加密操作。

    参考文档:

    https://blog.csdn.net/qq_41793222/article/details/80615946

  • 相关阅读:
    echarts官网上的动态加载数据bug被我解决。咳咳/。
    jquery中的jsonp和js中的jsonp还有配合php实现的jsonp。
    jquery中的done和always解决ajax问题
    vue2.0使用watch监听对象属性
    gulp配合vue压缩代码格式化
    支持flv的播放神器
    前端组件化-Web Components【转】
    自定义异步加载资源插件
    【leetcode刷题笔记】Two Sum
    【leetcode刷题笔记】Longest Common Prefix
  • 原文地址:https://www.cnblogs.com/cnsyear/p/12732113.html
Copyright © 2011-2022 走看看