[英]Encrypt Spring Boot Rest Api Query Param
我知道这个问题已被多次询问,但没有人回答我的问题,所以请不要将此标记为重复。
我需要使用 AES 在 rest API 中加密我的参数。 我创建了 2 个 API,用于加密和解密。
import AesTest;
import com.google.zxing.BarcodeFormat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.net.URLEncoder;
@RestController
@SpringBootApplication
public class BarcodeApplication {
public static void main(String[] args) {
SpringApplication.run(BarcodeApplication.class, args);
}
@GetMapping(value = "encrypt")
public String encrypt(@RequestParam BarcodeFormat barcodeFormat, @RequestParam(defaultValue = "this is test") String text, @RequestParam(defaultValue = "200") String width, @RequestParam(defaultValue = "200") String height, HttpServletResponse response) throws Exception {
System.out.println("barcodeFormat = " + barcodeFormat);
System.out.println("text = " + text);
System.out.println("width = " + width);
System.out.println("height = " + height);
response.setContentType("image/png");
String encryptQuery = AesTest.encrypt(barcodeFormat.toString() + "&" + text + "&" + width + "&" + height);
String urlEncodedData = URLEncoder.encode(encryptQuery, "UTF-8");
return urlEncodedData;
}
@RequestMapping(path = "barcode/{query}")
public String getMessage(@PathVariable("query") String query, HttpServletResponse response) throws Exception {
String decryptQuery = AesTest.decrypt(query);
String urlEncodedData = URLDecoder.decode(decryptQuery, "UTF-8");
String[] queryArr = urlEncodedData.split("&");
BarcodeFormat barcodeFormat = BarcodeFormat.valueOf(queryArr[0]);
String text = queryArr[1];
String width = queryArr[2];
String height = queryArr[3];
System.out.println("barcodeFormat = " + barcodeFormat);
System.out.println("text = " + text);
System.out.println("width = " + width);
System.out.println("height = " + height);
return null;
}
}`
下面是我的 AesTest 文件
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public class AesTest {
private static final String secretKey = "aesEncryptionKeyasdfghjk";
private static final String initVector = "encryptionIntVec";
public static String decrypt(String encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8));
SecretKeySpec skeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));
return new String(original);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static String encrypt(String value) {
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec(initVector.getBytes(StandardCharsets.UTF_8));
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.encodeBase64String(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
}
如果我使用http://localhost:8080/encrypt?text= test &height=50&barcodeFormat=CODE_128&width=200
它返回 9mXpav2uRPRsNufSRpj1aXiD5sBVgmjFoyst8cQp%2Bms%3D。
在第二个 API http://localhost:8080/barcode/9mXpav2uRPRsNufSRpj1aXiD5sBVgmjFoyst8cQp%2Bms%3D中传递这个值工作得很好。
但如果我更改第一个 API 的值,即http://localhost:8080/encrypt?text= testshri &height=50&barcodeFormat=CODE_128&width=200
它返回 Js%2Butdm9mS9jxSNBbvHeCJaKv7TqrtImTU%2FqcDWaSo8%3D。
在第二个 API 中传递此值会返回 HTTP 状态 400 – 错误请求。
更改查询参数中的文本会产生不同的结果。 我究竟做错了什么???
我认为问题出在您传递的参数上,因为它包含 ** %
** 字符,这可能会破坏请求 url。 因此,有必要在 URL 中使用数据之前对其进行编码,然后在检索期间对其进行解码。
这是您可以遵循的示例:
=== 编码:
private String encodeValue(String value) {
return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
}
@Test
public void givenRequestParam_whenUTF8Scheme_thenEncode() throws Exception {
Map<String, String> requestParams = new HashMap<>();
requestParams.put("key1", "value 1");
requestParams.put("key2", "value@!$2");
requestParams.put("key3", "value%3");
String encodedURL = requestParams.keySet().stream()
.map(key -> key + "=" + encodeValue(requestParams.get(key)))
.collect(joining("&", "http://www.baeldung.com?", ""));
assertThat(testUrl, is(encodedURL));
}
===解码:
private String decode(String value) {
return URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
}
@Test
public void givenRequestParam_whenUTF8Scheme_thenDecodeRequestParams() {
URI uri = new URI(testUrl);
String scheme = uri.getScheme();
String host = uri.getHost();
String query = uri.getRawQuery();
String decodedQuery = Arrays.stream(query.split("&"))
.map(param -> param.split("=")[0] + "=" + decode(param.split("=")[1]))
.collect(Collectors.joining("&"));
assertEquals("http://www.baeldung.com?key1=value 1&key2=value@!$2&key3=value%3",
scheme + "://" + host + "?" + decodedQuery);
}
您可以查看Baeldung ,它更详细地解释了这个概念。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.