双系统如何做接口认证-V2

现有A系统,B系统,A系统启动的时候调用B系统的注册接口API1(把A系统配置信息注册到B系统),A系统定时向B系统接口AP2发送心跳信息,B系统根据业务情况,调用A系统的业务接口AP3,请设计两系统的接口认证方式。

以下是为A系统(Python)与B系统(Spring Boot)设计的双向安全认证方案及关键代码实现,结合JWT、数字签名和HTTPS加密,确保注册、心跳、业务调用的安全可靠。


​整体认证方案设计​

​接口​ ​认证方式​ ​安全机制​ ​密钥管理​
API1(注册) 预共享密钥 + HTTPS HMAC签名 + TLS加密 预置静态密钥
API2(心跳) JWT + 时间戳签名 动态Token + 防重放 定期刷新Token
AP3(业务调用) 双向JWT + 请求签名 非对称加密 + Nonce校验 公钥证书交换

​一、接口认证流程与关键代码​

​1. 注册接口 API1​

​流程​​:A系统启动时,使用预共享密钥生成HMAC签名,B系统验证后返回长期凭证。
​安全机制​​:

  • HTTPS传输 + 预置密钥对请求签名
  • B系统存储A系统的公钥(用于后续验签)

​Python (A系统) 关键代码​​:

import requests
import hmac
import hashlib

def register_to_b():
    url = "https://b-system/api1"
    shared_secret = "pre-shared-key"
    config = {"system_id": "A", "public_key": "A_PUBLIC_KEY"}
    
    # 生成HMAC签名
    signature = hmac.new(
        shared_secret.encode(),
        json.dumps(config).encode(),
        hashlib.sha256
    ).hexdigest()
    
    headers = {"X-Signature": signature}
    response = requests.post(url, json=config, headers=headers, verify=True)  # 启用HTTPS验证
    return response.json()  # 返回{"access_token": "xxx", "refresh_token": "yyy"}

​Spring Boot (B系统) 关键代码​​:

 
  
@RestController
public class RegistrationController {
    @PostMapping("/api1")
    public ResponseEntity register(@RequestBody Map body, 
                                      @RequestHeader("X-Signature") String signature) {
        // 1. 验证HMAC签名
        String computedSig = HmacUtils.hmacSha256Hex("pre-shared-key", body.toString());
        if (!computedSig.equals(signature)) {
            return ResponseEntity.status(401).body("Invalid signature");
        }
        
        // 2. 生成长期Token并存储公钥
        String accessToken = Jwts.builder().setSubject(body.get("system_id")).compact();
        redis.savePublicKey(body.get("system_id"), body.get("public_key")); // 存储公钥
        return ResponseEntity.ok(Map.of("access_token", accessToken));
    }
}

​2. 心跳接口 API2​

​流程​​:A系统使用JWT和当前时间戳签名,B系统验证Token有效性和时间戳防重放。
​安全机制​​:

  • 动态Token(JWT) + RSA签名
  • 时间戳窗口(±30秒)

​Python (A系统) 关键代码​​:

 
  
import jwt
import time

def send_heartbeat():
    token = "A_ACCESS_TOKEN"  # 注册时获取
    private_key = "A_PRIVATE_KEY"  
    timestamp = int(time.time())
    
    # 用私钥签名时间戳+Token
    signature = jwt.encode({"token": token, "ts": timestamp}, private_key, algorithm="RS256")
    
    # 发送请求
    response = requests.post(
        "https://b-system/api2",
        headers={"Authorization": f"Bearer {token}", "X-Signature": signature}
    )
    if response.status_code == 401:  # Token过期则刷新
        refresh_token()

​Spring Boot (B系统) 关键代码​​:

 
  
@PostMapping("/api2")
public ResponseEntity heartbeat(@RequestHeader("Authorization") String authHeader, 
                                    @RequestHeader("X-Signature") String signature) {
    // 1. 提取JWT并验证
    String token = authHeader.replace("Bearer ", "");
    if (!JwtUtils.validateToken(token)) {  // 校验JWT有效性
        return ResponseEntity.status(401).build(); 
    }
    
    // 2. 验证时间戳签名
    String publicKey = redis.getPublicKey("A"); 
    Claims claims = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(signature).getBody();
    long ts = claims.get("ts", Long.class);
    if (Math.abs(System.currentTimeMillis()/1000 - ts) > 30) {  // 防重放
        return ResponseEntity.status(403).body("Timestamp expired");
    }
    
    return ResponseEntity.ok().build();
}

​3. 业务调用接口 AP3​

​流程​​:B系统用私钥签名请求(含Nonce),A系统用B的公钥验签并校验Nonce。
​安全机制​​:

  • 双向JWT + RSA请求签名
  • Nonce防重放

​Spring Boot (B系统) 关键代码​​:

public void callA() {
    String bToken = "B_TO_A_TOKEN";  // A系统注册时颁发
    String payload = "{...}";
    String nonce = UUID.randomUUID().toString();
    long ts = System.currentTimeMillis();
    
    // 用B的私钥生成签名
    String signature = Jwts.builder()
        .claim("nonce", nonce)
        .claim("ts", ts)
        .signWith(SignatureAlgorithm.RS256, bPrivateKey)
        .compact();
    
    // 调用A系统接口
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Bearer " + bToken);
    headers.add("X-Signature", signature);
    new RestTemplate().post("https://a-system/ap3", new HttpEntity<>(payload, headers));
}

​Python (A系统) 关键代码​​:

from flask import Flask, request
import jwt

app = Flask(__name__)

@app.route('/ap3', methods=['POST'])
def handle_business():
    token = request.headers.get("Authorization").split()[1]
    signature = request.headers.get("X-Signature")
    
    # 1. 验证B系统的Token有效性
    if token != "B_TO_A_TOKEN": 
        return "Invalid token", 401
    
    # 2. 用B的公钥验证签名
    try:
        claims = jwt.decode(signature, "B_PUBLIC_KEY", algorithms=["RS256"])
        if claims["nonce"] in used_nonces:  # 校验Nonce是否重复
            return "Replay attack", 403
        used_nonces.add(claims["nonce"])
    except jwt.InvalidSignatureError:
        return "Invalid signature", 401
    
    return "Success", 200

​二、安全增强措施​

  1. ​传输层加密​
    • 所有接口强制HTTPS(TLS 1.3+)
  2. ​密钥管理​
    • A系统重启时生成新密钥对(Python:cryptography库)
    • B系统定期轮换JWT签名密钥(Spring Security配置)
  3. ​防攻击策略​
    • 心跳频率限制:Spring Security配置antMatchers("/api2").permitAll().rateLimit(1/min)
    • IP白名单:B系统调用AP3时校验A系统的预注册IP

​三、异常处理与容错​

​场景​ ​处理方案​
心跳丢失 A系统重试3次后触发重新注册
Token过期 A系统用refresh_token调用B的刷新接口
签名失效 B系统返回401并记录审计日志(ELK收集)

​方案优势​​:

  1. ​分层认证​​:注册接口独立保障系统信任,业务接口轻量化
  2. ​零信任设计​​:每次请求验证签名+时效,避免长期凭证泄露风险
  3. ​跨语言兼容​​:Python与Spring Boot通过标准JWT和HTTPS交互

你可能感兴趣的:(python,开发语言)