Http请求中的特殊字符

问题

一个 springboot 应用,包含如下 controller

@RestController
public class DemoController {@GetMapping("/get")public ResponseEntity<String> get(@RequestParam(value = "cid2") String cid2)

准备测试数据

String cid2 = "1;MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoJDsA9HldKEk8i/lbRxS8E13HlCBjg63CrDLF6ieQT+h7K9eRS5jH0VgYXLmWJLOnGLrH1324JaEYHbTmZgpVw==;eWxJY0hrdlBPYVMz;MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpto5kN5HEx/OvVTV2ux08EvneYb+cNx4g9G7ajgH41gBCl7G5JkbaYA7Wf9DxOks3Syu/NJPwhjbOz32L+BfTA==;hcHB3S1D5hgfe5Ar9DUKqW3SeCrvAgeXzt7RldZTh/qWCouFW6NqEZfycxe9Tqi9ehemNc1cMaAtAsC2Ng34hZsEN/cdyqGRcRTbYSpEtdL3GVbyIF5S9hTYD9wcvUMMhsnFIfUMZD0=";

发起请求

String url = UriComponentsBuilder.fromHttpUrl("http://localhost:8080/get").queryParam("cid2", cid2).toUriString();
ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);

发现问题,controller 接收到的数据为

1;MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoJDsA9HldKEk8i/lbRxS8E13HlCBjg63CrDLF6ieQT h7K9eRS5jH0VgYXLmWJLOnGLrH1324JaEYHbTmZgpVw==;eWxJY0hrdlBPYVMz;MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpto5kN5HEx/OvVTV2ux08EvneYb cNx4g9G7ajgH41gBCl7G5JkbaYA7Wf9DxOks3Syu/NJPwhjbOz32L BfTA==;hcHB3S1D5hgfe5Ar9DUKqW3SeCrvAgeXzt7RldZTh/qWCouFW6NqEZfycxe9Tqi9ehemNc1cMaAtAsC2Ng34hZsEN/cdyqGRcRTbYSpEtdL3GVbyIF5S9hTYD9wcvUMMhsnFIfUMZD0=

对比发现其中的加号变成了空格,而我们希望传递到服务端的是依然是加号。


 

原因分析

根据 URL 编码的规范,空格字符在 URL 查询字符串中通常会被编码为 +。这意味着当发送一个 URL 请求并将 + 作为查询参数时,浏览器和服务器会认为 + 是空格的替代符号。

举个例子:

假设你传递的 URL 是:Example Domain,param=hello+world 中的 + 会被自动解码为一个空格,最终得到的参数值就是 hello world,而不是原始的 hello+world

解决方法

通过 URLEncoder 进行编码

Java 的 URLEncoder 可以将特殊字符(如 ;, /, +, =, %)转义成 URL 编码的格式。例如,空格被编码为 +,而其他特殊字符会转换成以 % 开头的编码形式。

客户端预先编码,得到:

1%3BMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoJDsA9HldKEk8i%2FlbRxS8E13HlCBjg63CrDLF6ieQT%2Bh7K9eRS5jH0VgYXLmWJLOnGLrH1324JaEYHbTmZgpVw%3D%3D%3BeWxJY0hrdlBPYVMz%3BMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpto5kN5HEx%2FOvVTV2ux08EvneYb%2BcNx4g9G7ajgH41gBCl7G5JkbaYA7Wf9DxOks3Syu%2FNJPwhjbOz32L%2BBfTA%3D%3D%3BhcHB3S1D5hgfe5Ar9DUKqW3SeCrvAgeXzt7RldZTh%2FqWCouFW6NqEZfycxe9Tqi9ehemNc1cMaAtAsC2Ng34hZsEN%2FcdyqGRcRTbYSpEtdL3GVbyIF5S9hTYD9wcvUMMhsnFIfUMZD0%3D

服务端接受到(观察以下数据可以发现%在传输之前再次被编码为%25):

1%253BMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoJDsA9HldKEk8i%252FlbRxS8E13HlCBjg63CrDLF6ieQT%252Bh7K9eRS5jH0VgYXLmWJLOnGLrH1324JaEYHbTmZgpVw%253D%253D%253BeWxJY0hrdlBPYVMz%253BMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpto5kN5HEx%252FOvVTV2ux08EvneYb%252BcNx4g9G7ajgH41gBCl7G5JkbaYA7Wf9DxOks3Syu%252FNJPwhjbOz32L%252BBfTA%253D%253D%253BhcHB3S1D5hgfe5Ar9DUKqW3SeCrvAgeXzt7RldZTh%252FqWCouFW6NqEZfycxe9Tqi9ehemNc1cMaAtAsC2Ng34hZsEN%252FcdyqGRcRTbYSpEtdL3GVbyIF5S9hTYD9wcvUMMhsnFIfUMZD0%253D

服务端要对接收到的数据 decode 1 次才能得到客户端预先编码后的数据,decode 2 次才能获得我们想要传输的带特殊符号的数据。


 

POST 请求传递特殊字符

POST 请求中,数据被发送到请求体 body,而不是 URL 中,因此特殊字符不会被编码,以下两种方式都可以。

application/json

headers.setContentType(MediaType.APPLICATION_JSON);
Map<String, String> body = new HashMap<>();
body.put("cid2", cid2);RequestEntity<Map> requestEntity = new RequestEntity<>(body,headers,HttpMethod.POST,URI.create("http://localhost:8080/post")
);ResponseEntity<String> exchange = restTemplate.exchange(requestEntity, String.class);

application/x-www-form-urlencoded

headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("param", cid2);RequestEntity<MultiValueMap<String, String>> requestEntity = new RequestEntity<>(formData,headers,HttpMethod.POST,URI.create("http://localhost:8080/submit")
);ResponseEntity<String> exchange = restTemplate.exchange(requestEntity, String.class);


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/89511.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/89511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

告别手动报表开发!描述数据维度,AI 自动生成 SQL 查询 + Java 导出接口

Java 开发中&#xff0c;报表模块往往是 “隐形耗时大户”—— 产品经理要 “按地区、月份统计订单量”&#xff0c;开发者需先编写 SQL 查询&#xff0c;再手动开发导出接口&#xff0c;稍作调整又要重新调试&#xff0c;耗费大量时间在重复劳动上。飞算 JavaAI 通过 “数据维…

函数设计测试用例

//归并排序:public static void mergeSort(int[] a,int left,int right){if(left > right)return;int mid left(right -left)/2;mergeSort(a,left,mid);mergeSort(a,mid1,right);int[] tmp new int[a.length];int l left,r mid1,k left;while(l<mid && r<…

Vmware虚拟机使用仅主机模式共享物理网卡访问互联网

一、概述 Vmware虚拟机网卡模式有三种&#xff1a;桥接模式、仅主机模式、NAT模式。默认情况下&#xff0c;Vmware虚拟机使用仅主机模式不能访问互联网。因此&#xff0c;虚拟机可以共享宿主机的物理网卡访问互联网。 三种网卡模式的区别二、Vmware网络设置 2.1、调整虚拟网络 …

声画同步!5 个音视频素材适配的网站,创作更和谐

视频画面和背景音乐不搭&#xff1f;音效和动作不同步&#xff1f;好的作品&#xff0c;声音和画面必须像齿轮一样咬合。这 5 个专注 “声画同步” 的素材网站&#xff0c;能让音视频素材精准匹配&#xff0c;从旋律到节奏&#xff0c;从音效到画面&#xff0c;都默契十足&…

13.多种I/O函数

前言 之前的示例中&#xff0c;基于Linux的使用read&write函数完成数据I/O&#xff0c;基于Windows的则使用send&recv函数。这次的Linux示例也将使用send& recv函数&#xff0c;并讲解其与read&write函数相比的优点。还将介绍几种其他的I/O函数。 一、send &am…

设计模式五:桥模式(Bridge Pattern)

桥模式是一种结构型设计模式&#xff0c;它将抽象部分与其实现部分分离&#xff0c;使它们可以独立变化。这种模式通过提供桥梁结构将抽象和实现解耦。桥模式的结构桥模式包含以下主要角色&#xff1a;Abstraction&#xff08;抽象类&#xff09;&#xff1a;定义抽象接口&…

深入理解设计模式之模板模式:优雅地定义算法骨架

在软件开发中&#xff0c;我们经常会遇到这样的情况&#xff1a;多个类执行相似的操作流程&#xff0c;但每个类在流程的某些步骤上有自己特定的实现。如果为每个类都完整地编写整个流程&#xff0c;会导致大量重复代码&#xff0c;且难以维护。这时候&#xff0c;模板模式&…

基于单片机宠物喂食器/智能宠物窝/智能饲养

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 深夜加班时&#xff0c;你是否担心家中宠物饿肚子&#xff1f;出差旅途中&#xff0c;是否焦虑宠…

静态补丁脚本 - 修改 libtolua.so

直接改arm64的so&#xff0c; 使用python脚本。#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 静态补丁脚本 - 修改 libtolua.so 主要功能&#xff1a; 1. 修改 luaL_loadbuffer 函数&#xff0c;将跳转目标从 luaL_loadbufferx 改为 luaL_loadfilex 2. …

2-大语言模型—理论基础:详解Transformer架构的实现(2)

目录 1-大语言模型—理论基础&#xff1a;详解Transformer架构的实现(1)-CSDN博客https://blog.csdn.net/wh1236666/article/details/149443139?spm1001.2014.3001.5502 2.3、残差连接和层归一化 2.3.1、什么是层归一化&#xff1f; 2.3.2、层归一化的核心特点&#xff08…

SmartX 用户建云实践|富士康:基于榫卯企业云平台构建分布式云,支撑全球多地工厂重要产线

作为全球最大的电子科技智造服务商&#xff0c;富士康集团在全球范围内构建生产制造网络。为实现多厂区统一管理与降本增效&#xff0c;在逐步替代 VMware 虚拟化架构的过程中&#xff0c;富士康对比了自研 OpenStack Ceph 平台和 SmartX 超融合方案&#xff0c;最终选择基于 …

ADC选型设计

1、最大摆伏FSR&#xff1a; 0 ~ 4.096V&#xff0c;一般Vref要等于FSR 2、最大频率&#xff1a;根据奈奎斯特采样定理大于2倍的信号频率才够还原信号&#xff0c;所以选择20/50倍更好&#xff0c; 3、最小精度&#xff0c;对于一给定模拟输入&#xff0c;实际数字输出与理论预…

基于深度学习的火灾智能检测系统设计与实现

在各类安全事故中&#xff0c;火灾因其突发性强、破坏力大&#xff0c;一直是威胁人们生命财产安全的重大隐患。传统的火灾检测方式多依赖烟雾传感器、温度传感器等&#xff0c;存在响应滞后、易受环境干扰等问题。随着深度学习技术的飞速发展&#xff0c;基于计算机视觉的火灾…

HIVE实战处理(二十四)留存用户数

留存概念: 次X日活跃留存&#xff0c;次X日新增留存&#xff0c;也就是看今天的新增或活跃用户在后续几天的留存情况一、留存表的生成逻辑 因为用户活跃日期和留存的日期无法对齐所以搞了2级分区&#xff08;dt,static_day&#xff09; 1&#xff09;首先获得计算日D、根据要出…

W3C XHTML 活动:标准化的未来与交互式体验

W3C XHTML 活动:标准化的未来与交互式体验 概述 W3C(World Wide Web Consortium)是全球领先的互联网技术标准制定组织。XHTML,作为W3C推荐的标准之一,是一种基于XML的标记语言,旨在提供一个更加结构化、兼容性和可扩展性更高的网页内容表示方式。本文将围绕W3C的XHTML活…

Java-数构链表

1.链表 1.1链表的概念和结构 链表是一种物理存储结构上非连续存储结构&#xff0c;数据元素的逻辑顺序是通过链表中引用链接次序实现的。 这里大多讨论无头单向非循环链表。这种结构&#xff0c;结构简单&#xff0c;一般与其他数据结构结合&#xff0c;作为其他数据结构的子…

Windows系统软件游戏丢失找不到mgmtapi.dll修复解决方法

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

初识C++——开启新旅途

从今天开始主包也是掉入C这个深坑&#xff0c;上完课也是跟没上一样&#xff0c;所以写好博客复习还是很重要的&#xff0c;话不多说&#xff0c;进入正题~~1、命名空间(1)namespace的价值与作用在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变…

vue2 面试题及详细答案150道(141 - 150)

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

第十三章 Go包管理

文章目录使用logurs处理程序日志logrus 常用配置使用viper处理程序配置使用logurs处理程序日志 下载包&#xff0c;在终端执行命令 go get github.com/sirupsen/logrus官方示例 package mainimport (log "github.com/sirupsen/logrus" )func main() {log.WithFiel…