You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring MVC中如何对URL中的字段实体进行加密编码?

解决Spring MVC表单GET提交参数暴露的问题

首先得明确核心:GET请求的参数本身就会被放在URL里,这是HTTP协议的特性。要解决参数明文暴露的问题,有两种核心方案,你可以根据业务需求来选:

一、最省心的方案:改用POST请求

如果不需要生成可分享的URL,直接把请求方式改成POST是最简单有效的——POST请求的参数会放在请求体里,不会出现在URL中。

具体修改步骤:

  1. 修改main.jsp的表单:把method="get"改成method="post"
<form action="successA" method="post">
  1. 修改Controller的请求映射:把RequestMethod.GET换成RequestMethod.POST
@RequestMapping(value = "/successA", method = RequestMethod.POST)
public ModelAndView method(@Valid @ModelAttribute("bean") Bean bean, BindingResult result ) {
    // 原有逻辑完全不用改,正常处理表单提交即可
}

这个方案几乎零成本,也是最推荐的做法。

二、必须用GET?那就加密参数

如果因为业务需求(比如要生成可分享的链接)必须用GET,那只能对参数进行加密,让URL里的内容变成密文,后端再解密处理。这里要注意:你提到的URIEditor只是做URI标准编码(比如把空格转成%20),并不是加密,还是能看到明文,完全不适合你的场景。

实现步骤:

1. 前端提交前加密参数

我们可以用JavaScript在表单提交前把所有参数加密成一个字符串,再作为单个参数传递。这里以AES加密为例,需要引入crypto-js库:

在main.jsp里添加这段脚本:

<script src="https://cdn.jsdelivr.net/npm/crypto-js@4.1.1/crypto-js.min.js"></script>
<script>
// 监听表单提交事件
document.querySelector('form').addEventListener('submit', function(e) {
    e.preventDefault(); // 先阻止默认提交行为
    
    // 密钥和IV要和后端保持一致,建议用16位长度
    const secretKey = CryptoJS.enc.Utf8.parse('your16bitSecretKey');
    const iv = CryptoJS.enc.Utf8.parse('your16bitIV');
    
    // 收集所有表单参数
    const formData = new FormData(this);
    const paramObj = {};
    formData.forEach((val, key) => paramObj[key] = val);
    
    // 把参数转成JSON字符串再加密
    const encryptedStr = CryptoJS.AES.encrypt(
        JSON.stringify(paramObj),
        secretKey,
        { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
    ).toString();
    
    // 跳转到successA,把加密后的字符串作为data参数传递
    window.location.href = `successA?data=${encodeURIComponent(encryptedStr)}`;
});
</script>

2. 后端解密参数

修改Controller的方法,接收加密后的data参数,解密后转成你的Bean对象:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.StringUtils;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

@RequestMapping(value = "/successA", method = RequestMethod.GET)
public ModelAndView method(@RequestParam("data") String encryptedData, BindingResult result ) throws Exception {
    // 先判断参数是否为空
    if (!StringUtils.hasText(encryptedData)) {
        return new ModelAndView("main");
    }
    
    // 密钥和IV要和前端完全一致
    String key = "your16bitSecretKey";
    String ivStr = "your16bitIV";
    
    // 初始化解密工具
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
    IvParameterSpec iv = new IvParameterSpec(ivStr.getBytes());
    
    cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
    // 解密并转成JSON字符串
    byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
    String decryptedJson = new String(decryptedBytes);
    
    // 把JSON转成Bean对象(需要引入Jackson依赖)
    ObjectMapper objectMapper = new ObjectMapper();
    Bean bean = objectMapper.readValue(decryptedJson, Bean.class);
    
    // 保持原有参数校验逻辑
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<Bean>> violations = validator.validate(bean);
    if (!violations.isEmpty()) {
        for (ConstraintViolation<Bean> violation : violations) {
            result.addError(new FieldError("bean", violation.getPropertyPath().toString(), violation.getMessage()));
        }
        return new ModelAndView("main");
    }
    
    ModelAndView view = new ModelAndView("successAnother");
    view.addObject("bean", bean);
    return view;
}

别忘了在pom.xml里添加Jackson依赖(如果还没加的话):

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version>
</dependency>

关于URIEditor的说明

你提到的org.springframework.beans.propertyeditors.URIEditor其实是Spring用来处理URI类型属性的编辑器,它的作用是把字符串格式的URI转成URI对象,或者反过来把URI转成字符串——只是做URI的标准编码/解码(处理空格、特殊字符),根本不是加密,完全满足不了你隐藏参数内容的需求。举个简单的使用例子,但确实帮不到你:

@InitBinder
public void initBinder(WebDataBinder binder) {
    // 注册URIEditor,处理URI类型的属性
    binder.registerCustomEditor(URI.class, new URIEditor());
}

内容的提问来源于stack exchange,提问作者Ayush

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:35:35