fixedBug:Web Requeset Get请求URLEncoder 编码

文章目录

  • 前言
  • 一、"+"为什么被替换:
    • [2.1 URL 编码(Percent-Encoding)的核心规则](#2.1 URL 编码(Percent-Encoding)的核心规则)
    • [2.2 GET 请求中 + 被替换为空格的完整流程](#2.2 GET 请求中 + 被替换为空格的完整流程)
    • [2.3 为什么 Base64 密文容易出现这个问题?](#2.3 为什么 Base64 密文容易出现这个问题?)
  • 二、怎么处理:
    • [2.1 使用 URL 安全编码](#2.1 使用 URL 安全编码)
    • [2.2 生成的 URL 示例(编码前后对比)](#2.2 生成的 URL 示例(编码前后对比))
    • [2.3 后端Get接收参数自动解码](#2.3 后端Get接收参数自动解码)
    • [2.4 注意事项](#2.4 注意事项)
  • 总结

前言

问题场景:后端生成并返回给前端的字符串 中 有 "+" 但是前端 通过Get 请求将改参数传入后端后 "+"被替换成了" "。


一、"+"为什么被替换:

GET 请求中遇到 + 被替换为空格的核心原因是:+ 是 URL 编码中的特殊字符(代表空格),当包含 + 的字符串直接作为 GET 参数传输时,浏览器 / HTTP 客户端会自动将 + 解析为空格,服务器接收时就会出现替换问题------ 这是 URL 编码规范(RFC 3986)和 HTTP 传输的固有特性,并非代码错误,而是参数传输格式不符合规范导致的。

2.1 URL 编码(Percent-Encoding)的核心规则

URL 只能包含「字母、数字、- _ . ~」等安全字符,其他字符(如 /、+、=、& 等)属于「保留字符」或「不安全字符」,必须通过 %+十六进制ASCII码 编码后传输:

空格的 URL 编码是 %20,但早期为了简化,也常用 + 表示空格(这是 application/x-www-form-urlencoded 格式的约定); + 本身的 ASCII 码是 43,对应的 URL 编码是 %2B

2.2 GET 请求中 + 被替换为空格的完整流程

bash 复制代码
原始字符串:...ec+khJ1Qh...
↓ 浏览器/HTTP客户端(如OkHttp、HttpClient)自动解析
识别 `+` 为 URL 中的「空格占位符」
↓ 传输到服务器
服务器接收参数时,将 `+` 解码为空格 → ...ec  khJ1Qh...

2.3 为什么 Base64 密文容易出现这个问题?

当传输的参数是 Base64 编码的密文,而 Base64 编码的字符集包含 +、/、= 三个特殊字符:

复制代码
+:对应 URL 中的空格;
/:URL 中的路径分隔符;
=:URL 参数中的键值对分隔符;
这三个字符直接放在 GET 参数中都会被篡改,其中 + 是最容易触发的问题。

二、怎么处理:

2.1 使用 URL 安全编码

使用 JDK 自带 java.net.URLEncoder 类,可直接实现标准 URL 编码(注意字符集必须用 UTF-8),通过URLEncoder.encode(content, StandardCharsets.UTF_8); 进行编码

代码如下(示例):

c 复制代码
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

/**
 * URL 编码工具类(标准 URLEncode)
 */
public class UrlEncodeUtil {
    /**
     * 标准 URL 编码(适配 GET 参数)
     * @param content 待编码内容(如 Base64 密文)
     * @return 编码后的字符串
     */
    public static String encode(String content) {
        if (content == null || content.trim().isEmpty()) {
            return "";
        }
        // 关键:字符集必须用 UTF-8,且编码空格为 %20(而非 +)
        return URLEncoder.encode(content, StandardCharsets.UTF_8);
    }

    /**
     * 标准 URL 解码(后端接收参数时 SpringBoot 自动解码,此方法仅备用)
     * @param encodedContent 编码后的字符串
     * @return 原始内容
     */
    public static String decode(String encodedContent) {
        if (encodedContent == null || encodedContent.trim().isEmpty()) {
            return "";
        }
        try {
            return java.net.URLDecoder.decode(encodedContent, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("URL 解码失败", e);
        }
    }
}

2.2 生成的 URL 示例(编码前后对比)

处理阶段 内容示例
原始令牌(Base64) 954nFKV42Ox7K0qCdd/oE2wj3hJ4B/51I0IHSFWDHgztgBqxOE0ec+khJ1QhOEAP...
URL 编码后 954nFKV42Ox7K0qCdd%2FoE2wj3hJ4B%2F51I0IHSFWDHgztgBqxOE0ec%2BkhJ1QhOEAP...

可以看到:

复制代码
+ 被编码为 %2B;
/ 被编码为 %2F;
=(若有)被编码为 %3D;
这些编码后的字符在 GET 请求传输中不会被篡改,服务器接收后会自动还原。

2.3 后端Get接收参数自动解码

请求发送到后端时,SpringBoot 会自动对 @RequestParam 注解的参数做 URL 解码,无需手动处理:

java 复制代码
@GetMapping("/reset-password")
public String showResetPage(@RequestParam String token) {
    // token 已经是 URL 解码后的原始 Base64 令牌(+、/ 已还原)
    System.out.println("接收的令牌(已解码):" + token);
    // 后续验证令牌、展示重置页面...
    return "reset-password";
}

2.4 注意事项

  • 字符集必须统一:编码和解码都必须使用 UTF-8,否则会出现乱码(URLEncoder.encode 若不指定字符集,JDK8 及以上默认 UTF-8,但建议显式指定)。
  • 避免重复编码:不要对已编码的 URL 再次编码(如 encode(encode(token))),否则会导致 %2B 被编码为 %252B,服务器解码后得到 %2B 而非 +。
  • 特殊字符全覆盖:除了 +,Base64 中的 /、= 也会被 URL 解析器处理,标准 URLEncode 会一次性处理所有特殊字符,无需单独替换。
  • URL 长度限制:GET 请求的 URL 有长度限制(不同浏览器 / 服务器约 2048 字符),若你的令牌过长(如 512 位),建议: 优先使用 POST 请求传输令牌;或缩短令牌长度(如优化加密内容)。

总结

在使用Get 请求传递参数是+, /、= 如果不进行 URLEncode 进行编码,服务器会将改字符进行篡改,导致后端接收的参数与实际值出现偏差。

相关推荐
彭于晏Yan2 小时前
SpringBoot集成Druid连接多个数据源
java·spring boot·后端
lkbhua莱克瓦242 小时前
Apache Maven全面解析
java·数据库·笔记·maven·apache
爱编码的傅同学2 小时前
【线程的同步与互斥】初识互斥量与锁
android·java·开发语言
ChoSeitaku2 小时前
28.C++进阶:map和set封装|insert|迭代器|[]
java·c++·算法
2501_944526422 小时前
Flutter for OpenHarmony 万能游戏库App实战 - 收藏功能实现
android·java·开发语言·javascript·python·flutter·游戏
2501_944526422 小时前
Flutter for OpenHarmony 万能游戏库App实战 - 个人中心实现
android·java·javascript·python·flutter·游戏
u0104058362 小时前
企业微信审批事件回调的安全验证与Java HMAC-SHA256校验实现
java·安全·企业微信
牧小七2 小时前
java8的新特性
java
Jing_jing_X2 小时前
AI分析不同阶层思维 十:MQ从概念、底层原理到选型
java·架构·提升·薪资