Spring MVC中禁用URL解码以保留加密参数中的加号
解决URL查询参数中加号被转成空格的问题
这个坑我之前踩过!问题根源在于HTTP协议的URL编码规范:查询参数里的+号默认会被解析为空格,但你的加密内容里+是有效字符,一旦被替换就没法正常解密了。下面给你几个实用的解决方案,按推荐程度排序:
1. 改用POST请求传递加密内容
这是最稳妥的方案,完全避开URL参数的编码问题。把加密值放在请求体(表单或JSON)里,Spring不会自动替换其中的+号。
示例代码(表单方式):
@RequestMapping(value = "missedcall", method = [RequestMethod.POST]) fun missedCall(@RequestParam("v") encryptedValue: String, model: ModelMap): String { // 这里的encryptedValue会完整保留原始的+号 // 执行解密逻辑... return "处理结果" }
示例代码(JSON方式):
如果加密内容较长,用JSON格式更规范:
// 定义请求体数据类 data class MissedCallRequest(val v: String) @RequestMapping( value = "missedcall", method = [RequestMethod.POST], consumes = [MediaType.APPLICATION_JSON_VALUE] ) fun missedCall(@RequestBody request: MissedCallRequest, model: ModelMap): String { val encryptedValue = request.v // 执行解密逻辑... return "处理结果" }
2. 前端对加密内容做正确的URL编码
如果必须用GET请求,让前端在拼接URL时,用encodeURIComponent()对加密值进行编码,这样+会被转成%2B,后端解析时会自动还原成+。
前端示例(JavaScript):
const encryptedStr = "this+is+my+encrypted+string"; // 编码后得到 "this%2Bis%2Bmy%2Bencrypted%2Bstring" const encodedStr = encodeURIComponent(encryptedStr); const requestUrl = `http://myurl.com/missedcall?v=${encodedStr}`;
后端不用改代码,@RequestParam会自动把%2B解码为+,拿到正确的加密字符串。
3. 后端手动解析原始查询参数
如果前端没法修改,你可以直接从HttpServletRequest获取原始的查询字符串,自己解析参数,避开Spring自动替换+的逻辑。
示例代码:
@RequestMapping("missedcall") fun missedCall(request: HttpServletRequest, model: ModelMap): String { val queryString = request.queryString ?: "" // 手动提取v参数的原始值 val encryptedValue = queryString.split("&") .firstOrNull { it.startsWith("v=") } ?.substringAfter("v=") // 此时encryptedValue就是原始的"this+is+my+encrypted+string",保留了所有+号 // 执行解密逻辑... return "处理结果" }
4. 全局配置Spring MVC禁用参数自动解码
不推荐全局修改,但如果所有端点都需要保留+号,可以配置Spring MVC的UrlPathHelper,禁止自动解码请求参数:
配置类代码:
@Configuration class WebMvcConfig : WebMvcConfigurer { override fun configurePathMatch(configurer: PathMatchConfigurer) { val urlPathHelper = UrlPathHelper() // 关闭自动解码,这样@RequestParam拿到的是编码后的原始字符串 urlPathHelper.isUrlDecode = false configurer.urlPathHelper = urlPathHelper } }
注意:这种情况下,你拿到的参数是编码后的字符串(比如this+is+my+encrypted+string),如果参数里还有其他需要解码的字符(比如%20),你需要手动调用URLDecoder.decode()处理,但要注意不要把+转成空格——可以先把+替换成%2B再解码:
val decodedValue = URLDecoder.decode( encryptedValue.replace("+", "%2B"), StandardCharsets.UTF_8.name() )
内容的提问来源于stack exchange,提问作者Wheel Builder
相关产品推荐
相关产品推荐

