Common API Security Practices: Token, Timestamp, Signature, and Anti‑Replay Measures
This article explains how to secure API communication with tokens, timestamps, cryptographic signatures, duplicate‑submission prevention, and practical Spring Boot code examples, offering a comprehensive guide for protecting data exchange between services.
In real business scenarios, APIs often need to interact with third‑party systems, so protecting data during transmission is essential.
1. Token – an access token identifies the caller and reduces password transmission. Tokens are usually UUIDs stored in Redis; two types: API Token (for public endpoints) and User Token (for authenticated endpoints). Token validity can be single‑use or time‑limited.
2. Timestamp – a request timestamp prevents replay and DoS attacks; the server checks the time difference against a configurable window.
3. Sign – a signature generated by concatenating sorted non‑empty parameters, token, timestamp, nonce and a secret key, then applying MD5 (or other) hashing, ensures parameters are not tampered.
4. Preventing duplicate submissions – store the request sign in Redis with the same expiration as the timestamp; subsequent identical requests are rejected.
5. Usage flow – client obtains appId and key, requests an API token using appId, timestamp and sign, then calls public APIs; for user‑level APIs it logs in to receive a user token.
6. Example code (Spring Boot)
@Configuration
public class RedisConfiguration {
@Bean
public JedisConnectionFactory jedisConnectionFactory(){
return new JedisConnectionFactory();
}
@Bean
public RedisTemplate<String, String> redisTemplate(){
RedisTemplate<String, String> redisTemplate = new StringRedisTemplate();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
// serializer setup omitted for brevity
return redisTemplate;
}
} @Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
private static final String[] excludePathPatterns = {"/api/token/api_token"};
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
super.addInterceptors(registry);
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns(excludePathPatterns);
}
} @Component
public class TokenInterceptor extends HandlerInterceptorAdapter {
@Autowired
private RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
String timestamp = request.getHeader("timestamp");
String nonce = request.getHeader("nonce");
String sign = request.getHeader("sign");
Assert.isTrue(!StringUtils.isEmpty(token) && !StringUtils.isEmpty(timestamp) && !StringUtils.isEmpty(sign), "参数错误");
// timestamp validation
long interval = System.currentTimeMillis() - Long.valueOf(timestamp);
Assert.isTrue(interval < 5 * 60 * 1000, "请求超时,请重新请求");
// token existence
ValueOperations<String, TokenInfo> ops = redisTemplate.opsForValue();
TokenInfo tokenInfo = ops.get(token);
Assert.notNull(tokenInfo, "token错误");
// signature verification
String signString = ApiUtil.concatSignString(request) + tokenInfo.getAppInfo().getKey() + token + timestamp + nonce;
String signature = MD5Util.encode(signString);
Assert.isTrue(signature.equals(sign), "签名错误");
// duplicate submit check (if annotated)
NotRepeatSubmit notRepeat = ApiUtil.getNotRepeatSubmit(handler);
if (notRepeat != null) {
long expire = notRepeat.value();
Assert.isTrue(!redisTemplate.hasKey(sign), "请勿重复提交");
redisTemplate.opsForValue().set(sign, 0, expire, TimeUnit.MILLISECONDS);
}
return super.preHandle(request, response, handler);
}
}7. ThreadLocal usage – a ThreadLocal map can store request‑scoped data (e.g., the current user) so that any layer (controller, service, DAO) can retrieve it without passing parameters.
Overall, the article provides a practical reference for implementing common API security mechanisms such as token management, timestamp validation, request signing, duplicate‑submission protection, and contextual data handling with ThreadLocal.
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.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
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.
