什么是api签名认证
API 签名认证是一种常见的安全机制,确保请求是由授权的客户端发出的,并且在传输过程中没有被篡改。签名认证通常使用 HMAC(Hash-based Message Authentication Code)算法,并且包括以下步骤:
生成签名:客户端根据预定义的规则生成签名,通常包括请求参数、时间戳、API 密钥等。
发送请求:客户端将签名和其他必要信息添加到请求头或请求参数中,并发送请求。
验证签名:服务器接收到请求后,根据相同的规则重新生成签名,并与客户端发送的签名进行比较。如果匹配,则请求合法。
怎么使用
步骤 1:生成签名
生成签名的一般步骤如下:
- 确定需要签名的参数。
- 将参数按照约定的顺序拼接成一个字符串。
- 使用 HMAC 算法和预共享的密钥生成签名。
假设我们有以下参数需要签名:
- api_key
- timestamp
- nonce
- 预共享的密钥是 secret_key。
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class ApiSigner {
public static String generateSignature(String apiKey, String timestamp, String nonce, String secretKey) throws Exception {
String message = apiKey + timestamp + nonce;
Mac sha256Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
sha256Hmac.init(secretKeySpec);
byte[] signedBytes = sha256Hmac.doFinal(message.getBytes());
return Base64.getEncoder().encodeToString(signedBytes);
}
}
步骤 2:发送请求
将生成的签名和其他必要信息添加到请求头中,并发送请求。
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class ApiClient {
private static final String API_URL = "https://api.example.com/resource";
private static final String API_KEY = "your_api_key";
private static final String SECRET_KEY = "your_secret_key";
public static void main(String[] args) throws Exception {
String timestamp = String.valueOf(System.currentTimeMillis());
String nonce = "random_nonce"; // 生成随机字符串
String signature = ApiSigner.generateSignature(API_KEY, timestamp, nonce, SECRET_KEY);
HttpHeaders headers = new HttpHeaders();
headers.set("API-Key", API_KEY);
headers.set("Timestamp", timestamp);
headers.set("Nonce", nonce);
headers.set("Signature", signature);
HttpEntity<String> entity = new HttpEntity<>(headers);
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(API_URL, HttpMethod.GET, entity, String.class);
System.out.println(response.getBody());
}
}
步骤 3:验证签名
服务器端在接收到请求后,根据相同的规则重新生成签名,并与客户端发送的签名进行比较。
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class ApiVerifier {
private static final String SECRET_KEY = "your_secret_key";
public static boolean verifySignature(String apiKey, String timestamp, String nonce, String clientSignature) throws Exception {
String message = apiKey + timestamp + nonce;
Mac sha256Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(), "HmacSHA256");
sha256Hmac.init(secretKeySpec);
byte[] signedBytes = sha256Hmac.doFinal(message.getBytes());
String serverSignature = Base64.getEncoder().encodeToString(signedBytes);
return serverSignature.equals(clientSignature);
}
}
Spring Boot 控制器示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
@GetMapping("/resource")
public String getResource(@RequestHeader("API-Key") String apiKey,
@RequestHeader("Timestamp") String timestamp,
@RequestHeader("Nonce") String nonce,
@RequestHeader("Signature") String signature) throws Exception {
if (!ApiVerifier.verifySignature(apiKey, timestamp, nonce, signature)) {
return "Invalid signature";
}
// 处理业务逻辑
return "Resource content";
}
}