三方接口设计是实现系统功能的关键环节。设计一个安全、高效且易于维护的接口调用方案,对于保障系统稳定性、数据安全性和用户体验至关重要。
// 生成API密钥
public class ApiKeyGenerator {
public static String generateAccessKey() {
return UUID.randomUUID().toString();
}
public static String generateSecretKey() {
return Base64.getEncoder().encodeToString(new byte[16]);
}
}接口鉴权是验证请求合法性的重要环节。可通过以下方式进行鉴权:
// 签名验证
public class SignAuthInterceptor implements HandlerInterceptor {
private String secretKey;
public SignAuthInterceptor(String secretKey) {
this.secretKey = secretKey;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String timestamp = request.getHeader("timestamp");
String nonceStr = request.getHeader("nonceStr");
String signature = request.getHeader("signature");
if (isExpired(timestamp) || isNonceUsed(nonceStr)) {
throw new BusinessException("Invalid request");
}
String calculatedSignature = calculateSignature(request, secretKey);
if (!signature.equals(calculatedSignature)) {
throw new BusinessException("Invalid signature");
}
return true;
}
private boolean isExpired(String timestamp) {
long currentTime = System.currentTimeMillis() / 1000;
long requestTime = Long.parseLong(timestamp);
return currentTime - requestTime > 60; // 有效期为60秒
}
private boolean isNonceUsed(String nonceStr) {
// 检查nonceStr是否已使用,可使用Redis等存储方式
return false;
}
private String calculateSignature(HttpServletRequest request, String secretKey) throws UnsupportedEncodingException {
Map<String, Object> params = new HashMap<>();
Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
String name = parameterNames.nextElement();
String value = request.getParameter(name);
if (!"signature".equals(name)) {
params.put(name, URLEncoder.encode(value, "UTF-8"));
}
}
List<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
StringBuilder sb = new StringBuilder();
for (String key : keys) {
sb.append(key).append("=").append(params.get(key)).append("&");
}
sb.append(secretKey);
return DigestUtils.md5DigestAsHex(sb.toString().getBytes("UTF-8"));
}
}接口API设计包括URL、HTTP方法、请求参数和响应格式等细节。设计时应遵循RESTful原则,使接口更加简洁、易于理解。
/api/resources表示获取资源列表。// API接口设计
@RestController
@RequestMapping("/api/resources")
public class ResourceController {
@GetMapping
public Result<List<Resource>> getResources(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int limit) {
// 实现获取资源列表的逻辑
List<Resource> resources = new ArrayList<>();
return Result.success(resources);
}
@PostMapping
public Result<Resource> createResource(@RequestBody Resource resource) {
// 实现创建资源的逻辑
return Result.success(resource);
}
@PutMapping("/{resourceId}")
public Result<Void> updateResource(@PathVariable String resourceId, @RequestBody Resource resource) {
// 实现更新资源的逻辑
return Result.success();
}
@DeleteMapping("/{resourceId}")
public Result<Void> deleteResource(@PathVariable String resourceId) {
// 实现删除资源的逻辑
return Result.success();
}
}
public class Result<T> {
private int code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMessage("Success");
result.setData(data);
return result;
}
// Getter and Setter methods
}// 防止重放攻击
public class AntiReplayInterceptor implements HandlerInterceptor {
private RedisTemplate<String, String> redisTemplate;
public AntiReplayInterceptor(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String nonceStr = request.getHeader("nonceStr");
String timestamp = request.getHeader("timestamp");
if (isNonceUsed(nonceStr) || isExpired(timestamp)) {
throw new BusinessException("Invalid request");
}
return true;
}
private boolean isNonceUsed(String nonceStr) {
return redisTemplate.hasKey(nonceStr);
}
private boolean isExpired(String timestamp) {
long currentTime = System.currentTimeMillis() / 1000;
long requestTime = Long.parseLong(timestamp);
return currentTime - requestTime > 60;
// 有效期为60秒
}
}