Securing Spring Cloud Gateway with RSA, Timestamp and Signature Verification
This guide explains how to protect a Spring Cloud Gateway service from packet sniffing by using RSA asymmetric encryption, timestamp validation, unique request IDs stored in Redis, and MD5 signature checks, with complete Java and front‑end code examples.
RSA Asymmetric Encryption Overview
RSA is a public‑key algorithm whose security relies on the difficulty of factoring large integers. The example uses a 1024‑bit key pair generated with the JCE API.
Java RSA Utility (RSAUtils)
Provides methods to generate a key pair, encrypt a UTF‑8 string with a Base64‑encoded public key, and decrypt a Base64‑encoded ciphertext with a private key. It uses KeyPairGenerator, Cipher, and Apache Commons Codec for Base64 handling.
public static Map<String,String> generateRasKey() { /* generate 1024‑bit RSA key pair */ } public static String encrypt(String plain, String publicKey) { /* RSA encryption, return Base64 string */ } public static String decrypt(String cipherText, String privateKey) { /* RSA decryption, return plain text */ }Custom Exception
public class RsaException extends RuntimeException { private final String message; public RsaException(String message) { this.message = message; } }Unit Tests
Demonstrate key generation, encryption of a JSON payload, and decryption of a sample ciphertext.
@Test public void generateRsaKey() { Map<String,String> map = RSAUtils.generateRasKey(); System.out.println(map.get(RSAUtils.PUBLIC_KEY)); System.out.println(map.get(RSAUtils.PRIVATE_KEY)); } @Test public void testEncrypt() { JSONObject obj = new JSONObject(); obj.put("username","rosh"); obj.put("password","123456"); String data = obj.toJSONString(); String encrypt = RSAUtils.encrypt(data, PUBLIC_KEY); System.out.println(encrypt); } @Test public void testDecrypt() { String decrypt = RSAUtils.decrypt("Yeidauky/...", PRIVATE_KEY); System.out.println(decrypt); }Front‑End Encryption and Request Signing
The login page loads jQuery, jsencrypt and md5. The public key is set in JSEncrypt. Before sending a request the form data is:
Sorted by ASCII key order.
Serialized to JSON.
Signed with MD5 over json + requestId + timestamp.
Encrypted with RSA.
Sent as the request body with HTTP headers timestamp, requestId and sign.
var encrypt = new JSEncrypt();
encrypt.setPublicKey("MIGfMA0G...");
var data = JSON.stringify(sort_ASCII(form));
var timestamp = Date.now();
var requestId = getUuid();
var sign = MD5(data + requestId + timestamp);
$.ajax({
url: "/api/user/login",
type: "POST",
data: encrypt.encrypt(data),
beforeSend: function(xhr){
xhr.setRequestHeader("timestamp", timestamp);
xhr.setRequestHeader("requestId", requestId);
xhr.setRequestHeader("sign", sign);
},
contentType: "application/json;charset=utf-8"
});The query page follows the same pattern, encrypting the query string and adding the same three headers.
Spring Cloud Gateway Global Filter
A GatewayFilterConfig implements GlobalFilter and performs the following steps for every request:
Extract and validate timestamp (must be within 5 minutes).
Extract and validate requestId (must be unique for 5 minutes, stored in Redis).
Extract the MD5 sign header.
For non‑login URLs, verify the JWT token.
Decrypt the RSA‑encrypted request body using the private key.
Merge decrypted JSON fields with query parameters (if a param query parameter is present).
Re‑compute the MD5 signature over the merged parameters, requestId and timestamp; reject the request if the signatures differ.
Wrap the modified request in a ServerHttpRequestDecorator that supplies the decrypted body to downstream handlers.
Key Helper Methods
private Long getDateTimestamp(HttpHeaders headers) { /* parse, check 5‑minute window, throw if invalid */ } private String getRequestId(HttpHeaders headers) { /* read, check Redis for replay, store for 5 min, throw if invalid */ } private String getSign(HttpHeaders headers) { /* read sign header, throw if missing */ } private void checkSign(String sign, Long timestamp, String requestId, Map<String,Object> params) { /* compute MD5 and compare, throw if mismatch */ }Cached Body Output Message
The custom MyCachedBodyOutputMessage extends CachedBodyOutputMessage and stores the decrypted parameter map, requestId, sign and timestamp for later verification.
public void initial(Map<String,Object> paramMap, String requestId, String sign, Long dateTimestamp) { this.paramMap = paramMap; this.requestId = requestId; this.sign = sign; this.dateTimestamp = dateTimestamp; }Back‑End Controllers and Service
A simple UserController provides /login and /detail endpoints. The login method checks hard‑coded credentials ( admin / 123456) and returns a JWT token. The detail method returns a JSON object with user information.
Repository
https://gitee.com/zhurongsheng/springcloud-gateway-rsa
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
IT Architects Alliance
Discussion and exchange on system, internet, large‑scale distributed, high‑availability, and high‑performance architectures, as well as big data, machine learning, AI, and architecture adjustments with internet technologies. Includes real‑world large‑scale architecture case studies. Open to architects who have ideas and enjoy sharing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
