接口参数加密+时效性检验+签名

本文探讨了API接口的安全措施,包括参数加密、时效性检验及签名验证,通过实例展示了如何利用公钥、时间戳和私钥签名来保护API接口,防止未授权访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个API就是一把开启神圣之门的钥匙.
只有我的子民才能拿着它,
进入我的王国中.

API裸奔,接口暴露, 大门敞开,任何人都可以进入…
接口参数加上公钥,是我发给子民的一把钥匙 . 当一个小偷, 在某个夜黑风高的晚上拿走了这把钥匙, 它也能瞥见我王国的一面.
然后我会在接口参数中再加上时间戳,这是一把带有时间属性的钥匙.只要过了一定的时间,这把钥匙就会失效.就算小偷拿了这把钥匙,时间一过,也就会不起作用.
然而,小偷勤快的,按时蹲点.还是成功的偷走既具时效性,也有公钥的钥匙.
最终, 我吩咐大门守卫,一定要对的上暗号的才能进入.这是加入私钥的签名.

以上, API接口参数加密+ 时效性检验+ 签名.

TestUserController .java


    /**  
    * @Title: TestUserController.java
    * @Package com.jzt.ssm.controller
    * 
    * @author jzt
    * @date 2018-11-15
    * @version V1.0  
    */
    
package com.jzt.ssm.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.jzt.ssm.po.Result;
import com.jzt.ssm.po.UserCustom;
import com.jzt.ssm.service.UserinfoService;
import com.jzt.ssm.util.MD5;

    /**
 * @ClassName: TestUserController
 * 
 * @author jzt
 * @date 2018-11-15
 *
 */

@Controller
public class TestUserController {
	@Autowired
	private UserinfoService userinfoService;
	/**
	 * 
	 * 
	 * 用户登录
	    * @Title: userLogin
	    * 
	    * @param user(用户名+密码+公钥+时间戳)
	    * @return 登录成功,true,否则 false
	    * 
	    * @author jzt
	 * @throws Exception 
	 */
	@RequestMapping("/userLogin")
	public @ResponseBody Result userLogin(UserCustom user) throws Exception{
		Result result = new Result();
		
		//获得时间戳
		Date timeStamp = user.getTimeStamp();
		Map<String,String> keys = new HashMap<>();
		Date date = new Date();
		if(user.getTimeStamp()==null||timeStamp.getTime()==0||timeStamp.getTime()+ 20000 > date.getTime()){//接口时间失效
			result.setMessage("接口时效失效");
			result.setReturnCode(-1);
		}
		
		if(user.getAccessKey()==null||user.getAccessKey()==""||!keys.containsKey(user.getAccessKey())){ //后台没有该公钥
			result.setMessage("后台没有该公钥");
			result.setReturnCode(-2);
		}
		//公钥 + 私钥
		keys.put("zhangshan", "sdjfkasdgnkdkgdkjdlkg");
		keys.put("lisi", "sddsgjgjkljdgdjjgkfdkfdg");
		
		//使用TreeMap进行升序排
		Map<String,Object> params = new TreeMap<>();
		
		if(user.getAccessKey()!=null) params.put("accessKey", user.getAccessKey());
		if(user.getPassWd()!=null) params.put("passWd", user.getPassWd());
		if(user.getTimeStamp()!=null) params.put("timeStamp", user.getTimeStamp());
		if(user.getUserName()!=null) params.put("userName", user.getUserName());
		params.put("secretKey", keys.get(user.getAccessKey()));
		String paramsStr = "";
		Set<String> keySet = params.keySet();
		Iterator<String> it = keySet.iterator();
		while(it.hasNext()){
			Object key = it.next();
			Object value = params.get(key);
			paramsStr+= key+  "=" + value +"&";
		}
		paramsStr = paramsStr.substring(0,paramsStr.length()-1);
		String sign = MD5.encodeByMD5(paramsStr).toUpperCase();
		if(!sign.equals(user.getSign())){
			result.setMessage("签名失败");
			result.setReturnCode(-3);
		}
		Boolean checklogin = userinfoService.checklogin(user.getUserName(), user.getPassWd());
		if(checklogin){
			result.setMessage("登录成功");
			result.setReturnCode(1);
		}else{
			result.setMessage("用户或密码错误");
			result.setReturnCode(0);
		}
		return result;
		
	}
	

}

MD5.java

    /**  
    * @Title: MD5.java
    * @Package com.jzt.ssm.util
    * 
    * @author jzt
    * @date 2018-11-15
    * @version V1.0  
    */
    
package com.jzt.ssm.util;

import java.security.MessageDigest;


    /**
 * @ClassName: MD5
 * 
 * @author jzt
 * @date 2018-11-15
 *
 */

public class MD5 {
	/** 十六进制下数字到字符的映射数组 */
	  private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; 
	  /**
     * 对字符串进行MD5编码
     * @param originString
     * @return
     */ 
	  public static String encodeByMD5(String originString) {
		  if (originString != null){
			  try { 
				  MessageDigest md = MessageDigest.getInstance("MD5");
				  byte[] results = md.digest(originString .getBytes());
				  String resultString = byteArrayToHexString(results); 
				  return resultString.toUpperCase(); 
				  } catch (Exception ex) {
					  ex.printStackTrace(); 
					  } 
			  } 
		  return null; 
		  } 
	  /**
     * 转换字节数组为16进制字串
     * 
     * @param b  字节数组
     * @return 十六进制字串
     */ 
	  private static String byteArrayToHexString(byte[] b) {
		  StringBuffer resultSb = new StringBuffer(); 
		  for (int i = 0; i < b.length; i++) { 
			  resultSb.append(byteToHexString(b[i]));
			  } 
		  return resultSb.toString(); 
		  } 
	  /**
     * 将一个字节转化成16进制形式的字符串
     * @param b
     * @return
     */ 
	  private static String byteToHexString(byte b) {
		  int n = b; 
		  if (n < 0) 
			  n = 256 + n; 
		  int d1 = n / 16; 
		  int d2 = n % 16; 
		  return hexDigits[d1] + hexDigits[d2]; 
	}	
}

User.java和UserCustom.java

    /**  
    * @Title: User.java
    * @Package com.jzt.ssm.po
    * 
    * @author jzt
    * @date 2018-11-15
    * @version V1.0  
    */
    
package com.jzt.ssm.po;


    /**
 * @ClassName: User
 * 
 * @author jzt
 * @date 2018-11-15
 *
 */

public class User {
	private String userName;
	private String passWd;
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassWd() {
		return passWd;
	}
	public void setPassWd(String passWd) {
		this.passWd = passWd;
	}
}


    /**  
    * @Title: UserCustom.java
    * @Package com.jzt.ssm.po
    * 
    * @author jzt
    * @date 2018-11-15
    * @version V1.0  
    */
    
package com.jzt.ssm.po;

import java.util.Date;


    /**
 * @ClassName: UserCustom
 * 
 * @author jzt
 * @date 2018-11-15
 *
 */

public class UserCustom extends User {
	
	
	//时间戳
	private Date timeStamp;
	//公钥
	private String accessKey;
	
	//签名
	private String sign;
	
	public String getSign() {
		return sign;
	}
	public void setSign(String sign) {
		this.sign = sign;
	}
	public Date getTimeStamp() {
		return timeStamp;
	}
	public void setTimeStamp(Date timeStamp) {
		this.timeStamp = timeStamp;
	}
	public String getAccessKey() {
		return accessKey;
	}
	public void setAccessKey(String accessKey) {
		this.accessKey = accessKey;
	}
	
	

}

Result.java

    /**  
    * @Title: Result.java
    * @Package com.jzt.ssm.po
    * 
    * @author jzt
    * @date 2018-11-15
    * @version V1.0  
    */
    
package com.jzt.ssm.po;


    /**
 * @ClassName: Result
 * 
 * @author jzt
 * @date 2018-11-15
 *
 */

public class Result {
	private String message;
	private int returnCode;
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
	public int getReturnCode() {
		return returnCode;
	}
	public void setReturnCode(int returnCode) {
		this.returnCode = returnCode;
	}
	
}
<think>嗯,用户这次的问题聚焦在API接口安全防护上,结合之前讨论的MVCC技术背景,ta可能是在设计电商系统时考虑到全链路安全——从数据库并发控制到对外接口防护。用户引用的三份材料都强调API作为数据交换通道的脆弱性,特别是未授权访问和注入攻击风险。 从实际架构角度看,API安全需要分层实施:最外层是传输加密,中间是身份认证和权限控制,最内层是数据操作安全。用户提到的HTTPS[^1]属于基础传输层防护,但真正的难点在于如何精细控制数据访问权限。比如电商场景中,订单查询API需要确保用户只能查自己的订单,而商家管理后台的API要防止越权访问其他店铺数据。 注意到用户引用材料中特别提到某电商平台因API漏洞导致数据泄露的案例[^2],这说明攻击者往往利用业务逻辑漏洞而非技术漏洞。因此除了常规的JWT和OAuth方案,还需要关注:1)接口参数的业务合法性校验(如防止通过篡改user_id参数越权);2)敏感数据返回时的脱敏规则(如银行卡号只显示后四位)。 另外,用户之前研究过MVCC的版本控制机制,这个思路其实可以延伸到API安全领域——为每个API请求创建带有时效性的访问凭证(类似Read View的事务快照概念),确保即使凭证泄露,攻击者也无法获取最新数据。这种动态凭证机制在金融行业API设计中应用广泛。 最后,用户没有明确说明当前系统阶段,但提到“防止数据泄露和非法访问”这个双重目标,建议补充回答中关于API调用行为监控的部分,因为事后审计往往是发现未授权访问的最后防线。</think>保障API接口安全需要构建多层次防护体系,以下是关键措施及实现方案: --- ### 一、认证与授权机制 1. **严格身份认证** - **OAuth 2.0/OpenID Connect**: ```mermaid graph LR A[客户端] -->|请求授权| B(授权服务器) B -->|发放Access Token| A A -->|携带Token访问| C[资源服务器] C -->|验证Token| D[返回数据] ``` - **JWT(JSON Web Token)**: 使用数字签名验证Token完整性,示例结构: `Header.Payload.Signature` 通过`RS256`非对称加密防止篡改[^1] 2. **精细化权限控制** - **RBAC(基于角色的访问控制)**: ```python # 伪代码示例 def check_permission(user_role, api_endpoint): return user_role in permissions_map[api_endpoint] ``` - **ABAC(基于属性的访问控制)**: 动态评估请求属性(如IP、时间、设备指纹) --- ### 二、数据传输防护 1. **强制HTTPS加密** - 启用TLS 1.3+协议 - 配置HSTS(HTTP Strict Transport Security) `Strict-Transport-Security: max-age=31536000; includeSubDomains` 2. **敏感数据额外加密** - 端到端加密(E2EE): ```mermaid graph LR 客户端 -->|AES-256加密数据| 服务端 服务端 -->|解密后处理| 业务系统 ``` - 支付类接口使用**国密SM4算法** --- ### 三、输入输出安全 1. **输入验证与过滤** - 正则表达式校验参数格式: `^[a-zA-Z0-9_]{4,20}$`(用户名规则) - 参数化查询防止SQL注入: ```java // Java PreparedStatement示例 String sql = "SELECT * FROM users WHERE id = ?"; PreparedStatement stmt = conn.prepareStatement(sql); stmt.setInt(1, userId); ``` 2. **输出敏感数据脱敏** ```python # 手机号脱敏示例 def mask_phone(phone): return phone[:3] + "****" + phone[7:] ``` 3. **速率限制(Rate Limiting)** - 令牌桶算法控制访问频率: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 75 X-RateLimit-Reset: 1663686000 ``` --- ### 四、进阶防护策略 | **防护层** | **技术方案** | **作用** | |------------------|----------------------------------|------------------------------| | API网关 | Kong/Apache APISIX | 统一入口管理、流量控制 | | Web应用防火墙 | ModSecurity/云WAF | 阻断SQL注入、XSS攻击 | | 审计日志 | ELK(Elasticsearch, Logstash, Kibana) | 记录所有API请求 | | 密钥管理 | HashiCorp Vault/AWS KMS | 安全存储API密钥 | --- ### 五、持续安全实践 1. **渗透测试** 定期执行: - Burp Suite扫描API端点 - OWASP ZAP漏洞检测 2. **安全开发流程** ```mermaid graph LR A[需求设计] --> B[威胁建模] B --> C[安全编码] C --> D[自动化扫描] D --> E[人工审计] E --> F[上线监控] ``` 3. **实时监控告警** - 异常行为检测:同一IP每秒>50次调用触发告警 - 敏感操作二次认证(如删除API) > **关键提示**:电商平台需特别关注订单查询、支付回调等高风险接口,建议对这类接口实施**双向证书认证**(mTLS)[^3]。 ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涛歌依旧fly

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值