繁体   English   中英

加密 Spring Boot Rest Api 查询参数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM