springboot对于@PathVariable自动解码问题

复制代码
@GetMapping("/getFile/{key}")
public void filePreview(@PathVariable("key") String key, HttpServletResponse response) {

}

测试如下:

复制代码
// 源字符串(urlencode前)A:MwbR64EbzUpX5MDnA3qb8yiTXUlbPegQqiNxuT8m7lbJ/k5THwkM+UvaRWWd7PzFVdZoGHx/GEPxm75LJZxKq1fqCdr3PKT/5P7qqoZm9AbN4n4kZ/z9uA==
// urlencode后  B: MwbR64EbzUpX5MDnA3qb8yiTXUlbPegQqiNxuT8m7lbJ%2Fk5THwkM%2BUvaRWWd7PzFVdZoGHx%2FGEPxm75LJZxKq1fqCdr3PKT%2F5P7qqoZm9AbN4n4kZ%2Fz9uA%3D%3D  (/变成了%2F,+变为%2B,=变成%3D)
//对传入的B字符串 springboot自动解码后 C:MwbR64EbzUpX5MDnA3qb8yiTXUlbPegQqiNxuT8m7lbJ%2Fk5THwkM+UvaRWWd7PzFVdZoGHx%2FGEPxm75LJZxKq1fqCdr3PKT%2F5P7qqoZm9AbN4n4kZ%2Fz9uA==(和原来的不太一样%2F没有解码成/)
// srpingboot自动解码后的C字符串 再 使用urldecode decode后的 D: MwbR64EbzUpX5MDnA3qb8yiTXUlbPegQqiNxuT8m7lbJ/k5THwkM UvaRWWd7PzFVdZoGHx/GEPxm75LJZxKq1fqCdr3PKT/5P7qqoZm9AbN4n4kZ/z9uA==   %2B 解码变成了空格了
//没有自动解码直接decode,也就是对 B 直接解码后  E:MwbR64EbzUpX5MDnA3qb8yiTXUlbPegQqiNxuT8m7lbJ/k5THwkM+UvaRWWd7PzFVdZoGHx/GEPxm75LJZxKq1fqCdr3PKT/5P7qqoZm9AbN4n4kZ/z9uA==  (这个和源字符串一致)
//将springboot自动解码后的字符串中+替换成%2B再解码:MwbR64EbzUpX5MDnA3qb8yiTXUlbPegQqiNxuT8m7lbJ/k5THwkM+UvaRWWd7PzFVdZoGHx/GEPxm75LJZxKq1fqCdr3PKT/5P7qqoZm9AbN4n4kZ/z9uA==(和源字符串一致)-->最终解决方案

Spring Boot在处理 @RequestParam@PathVariable 等注解时,默认会自动进行一次URL解码。但它的解码方式取决于容器和版本,有时会出现:

  • %2F 没有被解码(出于安全考虑,防止路径遍历攻击)

  • %2B 被解码成了空格(+ 在URL编码的 application/x-www-form-urlencoded 中确实代表空格)

key如果包含特殊字符,必须进行urlencode,但springboot接收时会自动对key进行decode的,但测试发现有些字符串并没有decode,而且代码如果直接decode这个自动解码后的字符串解码出来的字符串可能包含空格!

  • URLDecoder.decode()默认将+转为空格,但保留%20为空格

  • Spring的@PathVariable默认将%20转为空格,但保留+为加号

URL编码规则很明确:

  • 只有空格 会被编码为 %20+

  • 其他字符(如字母、数字、中文等)都会编码为 %XX 形式

  • 解码时,%20+ 才会被转回空格

方案一:获取原始参数值(推荐)

如果你需要自己完全控制解码过程,可以直接获取原始请求参数,避免Spring Boot的自动解码干扰

相关推荐
benbenAItalk6 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
sunshine22 girl6 小时前
Java学习二 基本语法2, 算术运算符
java·学习
niucloud-admin6 小时前
JAVA V6 多商户商城 开发文档——插件目录结构
java·开发语言
2601_962885726 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
滕州市燕猫虎计算机科技工作室个体工商户6 小时前
Java锁
java·开发语言
西瓜太郎12347 小时前
Claude Code、Codex CLI、Gemini CLI 能否共用一枚 Key?先看协议选择矩阵
前端·api 网关·claude code·gemini cli·codex cli
多加点辣也没关系7 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
shehuiyuelaiyuehao8 小时前
1计算机是如何工作的
java·计算机网络
陈随易9 小时前
在Finch用了62亿词元,我认为这是新一代Agent工具之神
前端·人工智能·后端
letisgo59 小时前
JAVA 高级进阶07篇《@Transactional失效的8个场景:代理机制到传播行为》
java·面试·transactional·spring事务·aop动态代理