How to Build Secure, Idempotent APIs: Keys, Tokens, and Anti‑Replay Strategies
This article explains how to design secure and reliable APIs for third‑party integration by covering API key generation, AK/SK authentication, callback URLs, permission models, token mechanisms, signature creation, replay‑attack prevention, HTTPS encryption, rate limiting, logging, data masking, idempotency, versioning, standardized response formats and documentation tools.
API Design Overview
When providing interfaces to third‑party systems, data security, integrity, freshness and idempotency are essential; the design must include API keys, authentication, callback URLs and permission control.
1. API Key and Authentication
1.1 API Key Generation and Allocation
Each third‑party application receives an Access Key (AK) to identify the client and a Secret Key (SK) to sign and encrypt requests.
Access Key (AK) : identifier similar to a username.
Secret Key (SK) : confidential key used for signing, similar to a password.
1.2 Authentication
Clients create a signature (typically HMAC‑SHA256) from AK and request parameters and send it in headers; the server verifies the signature with the stored SK.
2. Callback Address
Third‑party apps provide a callback URL to receive asynchronous notifications, e.g., payment results.
3. Permission Control and Allocation
3.1 Permission Model
Permissions are assigned per appId, appKey and appSecret, allowing fine‑grained access.
appId : unique application identifier.
appKey : public key used in requests.
appSecret : private key paired with appKey for signing.
3.2 Token Mechanism
Clients send appKey and appSecret to obtain an accessToken; subsequent requests must include the token.
Client sends request with appKey and appSecret.
Server validates and returns a token.
Client includes token in later requests.
4. Signature and Replay‑Attack Prevention
4.1 Signature Rules
Requests include appId, appSecret, timestamp, nonce and a signature generated from these values to ensure integrity.
Timestamp : limits request validity (e.g., 5 minutes).
Nonce : random value to prevent duplicate submissions.
Signature : computed from parameters and appSecret.
4.2 Anti‑Replay
Server checks timestamp freshness and nonce uniqueness; repeated nonces are rejected.
5. Simplified Interface Scenarios
Two common cases: public open APIs without keys (using the same value for appId, appKey and appSecret) and single‑permission configurations where appId and appKey are identical.
6. API Design Example
Basic CRUD endpoints for a resource with URL, HTTP method, parameters and response codes.
1.1 List Resources
URL : /api/resources Method : GET Params : page (optional), limit (optional)
Response : 200 OK with JSON array.
1.2 Create Resource
URL : /api/resources Method : POST Params : name (required), description (optional)
Response : 201 Created with new resource ID.
1.3 Update Resource
URL : /api/resources/{resourceId} Method : PUT Params : resourceId (path), name (optional), description (optional)
Response : 200 OK.
1.4 Delete Resource
URL : /api/resources/{resourceId} Method : DELETE Params : resourceId (path)
Response : 204 No Content.
2. Security Considerations
2.1 Use HTTPS Encryption
All API traffic must be transmitted over HTTPS to protect data from eavesdropping and tampering.
2.2 Prevent Replay Attacks
Include timestamp and nonce in each request; the server validates the timestamp range and ensures the nonce has not been used before.
2.3 Data Tampering Protection
Encrypt sensitive fields (e.g., passwords) and use TLS to guarantee confidentiality and integrity.
2.4 AK/SK Authentication
Server validates requests using the stored AK/SK pair; only authorized clients can access protected endpoints.
3. Anti‑Replay Best Practices
3.1 Timestamp and Nonce
Client generates a current timestamp and a unique nonce for every request.
GET /api/resources?page=1&limit=20×tamp=1645412345&nonce=abc1233.2 Signature Verification
Server recomputes the signature from received parameters and compares it with the provided sign value.
3.3 Signature Expiration
Signatures are considered invalid after a short period (e.g., 60 seconds).
3.4 Nonce Storage
Server stores used nonces and rejects any request containing a duplicate nonce.
public boolean isNonceUsed(String nonce) {<br/> if (nonceCache.contains(nonce)) {<br/> nonceCache.add(nonce); // 将Nonce加入缓存<br/> }<br/>}4. TLS Setup (Java Example)
SSLContext sslContext = SSLContext.getInstance("TLS");<br/>KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());<br/>keyStore.load(new FileInputStream("keystore.jks"), "password".toCharArray());<br/>KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());<br/>kmf.init(keyStore, "password".toCharArray());<br/>TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());<br/>sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());<br/>URL url = new URL("https://api.example.com/endpoint");<br/>HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();<br/>connection.setSSLSocketFactory(sslContext.getSocketFactory());5. AK/SK Management
5.1 Generation
Generate AK with UUID or random string; generate SK with a strong encryption algorithm.
5.2 Storage
Store credentials in a database table.
CREATE TABLE api_credentials (<br/> id INT AUTO_INCREMENT PRIMARY KEY,<br/> app_id VARCHAR(255) NOT NULL,<br/> access_key VARCHAR(255) NOT NULL,<br/> secret_key VARCHAR(255) NOT NULL,<br/> valid_from DATETIME NOT NULL,<br/> valid_to DATETIME NOT NULL,<br/> enabled TINYINT(1) NOT NULL DEFAULT 1,<br/> allowed_endpoints VARCHAR(255),<br/> created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP<br/>);5.3 Secure Transmission
Transmit AK and SK only over HTTPS.
6. API Optimization
6.1 Use POST for Sensitive Operations
POST keeps parameters in the request body, avoiding exposure in URLs.
6.2 IP Whitelist
Allow only trusted IP addresses to access the API.
6.3 Rate Limiting per IP
Use Redis to count requests per IP and endpoint, rejecting when the limit is exceeded.
String key = "ip:" + ip + ":endpoint:" + endpoint;<br/>long count = redisTemplate.opsForValue().increment(key, 1);<br/>redisTemplate.expire(key, 1, TimeUnit.MINUTES);<br/>if (count > 100) {<br/> throw new RateLimitException("请求过于频繁,请稍后再试");<br/>}6.4 Request Logging (AOP)
@Around("execution(* com.example.api.*.*(..))")<br/>public Object logRequest(ProceedingJoinPoint joinPoint) throws Throwable {<br/> Object[] args = joinPoint.getArgs();<br/> System.out.println("Request Args: " + Arrays.toString(args));<br/> Object result = joinPoint.proceed();<br/> System.out.println("Response: " + result);<br/> return result;<br/>}6.5 Sensitive Data Masking
Mask or encrypt fields such as ID numbers before logging or returning them.
6.6 Idempotency
Use a globally unique request ID (UUID) stored in Redis; if the ID already exists, reject the duplicate request.
String uniqueId = UUID.randomUUID().toString();<br/>if (redisTemplate.hasKey(uniqueId)) {<br/> return "Request already processed";<br/>}<br/>redisTemplate.opsForValue().set(uniqueId, "processed", 10, TimeUnit.MINUTES);6.7 Versioning
Include version numbers in the URL (e.g., /v1/users) to maintain backward compatibility.
6.8 Standard HTTP Status Codes
200 – Success
400 – Client error
404 – Not found
500 – Server error
6.9 Unified Response Format
All responses follow a JSON structure with code, message and data fields.
public Result fillData(Object data) {<br/> // set code, message, data<br/>}6.10 API Documentation
Generate interactive docs with Swagger to aid development and testing.
6.11 Signature Generation
public String generateSignature(Map<String, String> params, String secret) {<br/> StringBuilder sb = new StringBuilder();<br/> params.entrySet().stream()<br/> .sorted(Map.Entry.comparingByKey())<br/> .forEach(entry -> sb.append(entry.getKey()).append(entry.getValue()));<br/> return DigestUtils.md5DigestAsHex(sb.toString().getBytes()).toUpperCase();<br/>}6.12 Token + Signature
Combine a short‑lived token with a request signature to strengthen security.
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.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
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.
