当前位置: 首页 > news >正文

开放平台设计之接口签名认证

前言

当前时代,数据是王道!当我们自己的平台有了足够大的数据量,就有可能诞生一个开放平台宫第三方分析、使用。那么我们怎么去实现对外部调用接口的控制与鉴权呢?这是我们今天的重点——接口签名认证!!!

签名认证

开放平台会为每一位注册用户分配一个对应账户API KEY和秘钥API SECRET。我们为了保证接口的安全性,用户在每次接口的调用都需要上传一个所谓的签名(基于API KEYAPI SECRET获取)

签名认证步骤:

  1. 首先生成一个Unix时间戳timestamp,时间精确到毫秒【即1970年1月1日(UTC/GMT的午夜)开始所经过的毫秒数】;
  2. 生成随机数nonce(注:目前定义的是32位的,可以通过随机数工具类生成) ;
  3. 1)将timestamp、nonce、API_KEY 这三个字符串依据“字符串首位字符的ASCII码”进行升序排列(排序过程中若出现ASCII码值相同的情况,则依次递增对下一位进行比较)(这种排序,”也就是俗称的字典序“),并将排序后的结果拼接成为一个字符串join_str;
    2)接下来在用API_SECRET对上面生成这个字符串join_str做hmac-sha256 签名,并且以16进制编码,得到signature
  4. 将上述得到的timestampnonce,signature,与 API_KEY按照 #{k}=#{v}并以 ',' 为区分拼接在一起形成新的字符串,这就是要返回签名认证字符串authorization;
  5. 当完成以上4步,我们就可以获取最终的签名认证字符串了。调用接口时,将通过签名认证步骤得到的值authorization 传给HTTP HEADER的Authorization对应的值;请求体部分按照相对应文档请求参数说明正确填写,正常发送请求,即可完成一次接口调用。

下面以java代码举例:

假设 API_KEY = "233453f1d1eb4eb5a5ad9c8dac0d02cc";
API_SECRET = "444af44cd3a247c594438fb60d7b1d52";

1. 获得timestamp(unix时间戳),返回timestamp :"1633431976787"

实现方式:

 String timestamp = Long.toString(System.currentTimeMillis()); 

2. 获得随机nonce,返回nonce: "3isQFsTjsnNOLvIPXhf3HlW17WSfQqp9"

可用下面方式实现:

String nonce = RandomStringUtils.randomAlphanumeric(32);

3.将timestamp、nonce、API_KEY 这三个字符串依据“字符串首位字符的ASCII码”进行升序排列(排序过程中若出现ASCII码值相同的情况,则依次递增对下一位进行比较),并join成一个字符串,返回join_str:"1633431976787233453f1d1eb4eb5a5ad9c8dac0d02cc3isQFsTjsnNOLvIPXhf3HlW17WSfQqp9"

可用下面方式实现:

public static String genOriString(String timestamp,String nonce,String API_KEY){ArrayList<String> beforesort = new ArrayList<String>();beforesort.add(API_KEY);beforesort.add(timestamp);beforesort.add(nonce);Collections.sort(beforesort, new SpellComparator());StringBuffer aftersort = new StringBuffer();for (int i = 0; i < beforesort.size(); i++) {aftersort.append(beforesort.get(i));}String join_str = aftersort.toString();return join_str;}

4. 用API_SECRET对join_str做hmac-sha256签名,且以16进制编码,返回signature:"7d37d14406323f0ab30d1d4db1e7f2eb27abac42f3de00d619025108fa6cd5e4"

可用下面方式实现:

public static String genEncryptString(String join_str, String API_SECRET){Key sk = new SecretKeySpec(API_SECRET.getBytes(), "HmacSHA256");Mac mac = Mac.getInstance(sk.getAlgorithm());mac.init(sk);final byte[] hmac = mac.doFinal(join_str.getBytes());//完成hmac-sha256签名StringBuilder sb = new StringBuilder(hmac.length * 2);Formatter formatter = new Formatter(sb);for (byte b : hmac) {formatter.format("%02x", b);}String signature = sb.toString();//完成16进制编码return signature;}

5. 将上述的值按照 #{k}=#{v} 并以 ',' join在一起,返回签名认证字符串:
"key=2371d3f1d1eb4eb5a5ad9c8dac0d02cc,timestamp=1638431976741,nonce=3isWSsTjsnNOLvIPXhf3HlW17WSfQqp9,signature=7d37d14406323f0ab30d1d4db1e7f2eb27abac42f3de00d619025108fa6cd5e4"

可用下面方式实现:

public static String genauthorization(String API_KEY, String timestamp, String nonce, String signature){String authorization = "key=" + API_KEY+",timestamp=" + timestamp+",nonce=" + nonce+",signature=" + signature;return authorization;}

6. 将该签名认证字符串赋值给HTTP HEADER 的 Authorization 中,完成一次接口访问。

DEMO

pom文件中添加一下支持

     <dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>RELEASE</version><scope>compile</scope></dependency>

具体实现代码:


import java.util.Comparator;public class SpellComparator implements Comparator<Object> {public int compare(Object o1, Object o2) {try{String s1 = new String(o1.toString().getBytes("GB2312"), "ISO-8859-1");String s2 = new String(o2.toString().getBytes("GB2312"), "ISO-8859-1");return s1.compareTo(s2);}catch (Exception e){e.printStackTrace();}return 0;}
}
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Formatter;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.client.ClientProtocolException;public class GenerateString {// 开放平台注册获取id(API KEY)public static final String id = "22bfe9745135";// 开放平台注册获取密钥(API SECRET)public static final String secret = "19fbdc10";private static final String HASH_ALGORITHM = "HmacSHA256";static String timestamp = Long.toString(System.currentTimeMillis());static String nonce = RandomStringUtils.randomAlphanumeric(32);public static String genOriString(String api_key){ArrayList<String> beforesort = new ArrayList<String>();beforesort.add(api_key);beforesort.add(timestamp);beforesort.add(nonce);Collections.sort(beforesort, new SpellComparator());StringBuffer aftersort = new StringBuffer();for (int i = 0; i < beforesort.size(); i++) {aftersort.append(beforesort.get(i));}String OriString = aftersort.toString();return OriString;}public static String genEncryptString(String genOriString, String api_secret)throws SignatureException {try{Key sk = new SecretKeySpec(api_secret.getBytes(), HASH_ALGORITHM);Mac mac = Mac.getInstance(sk.getAlgorithm());mac.init(sk);final byte[] hmac = mac.doFinal(genOriString.getBytes());StringBuilder sb = new StringBuilder(hmac.length * 2);@SuppressWarnings("resource")Formatter formatter = new Formatter(sb);for (byte b : hmac) {formatter.format("%02x", b);}String EncryptedString = sb.toString();return EncryptedString;}catch (NoSuchAlgorithmException e1){throw new SignatureException("error building signature, no such algorithm in device "+ HASH_ALGORITHM);}catch (InvalidKeyException e){throw new SignatureException("error building signature, invalid key " + HASH_ALGORITHM);}}public static String genHeaderParam(String api_key, String api_secret) throws SignatureException{String GenOriString = genOriString(api_key);String EncryptedString = genEncryptString(GenOriString, api_secret);String HeaderParam = "key=" + api_key+",timestamp=" + timestamp+",nonce=" + nonce+",signature=" + EncryptedString;System.out.println(HeaderParam);return HeaderParam;}public static void main(String[] args) throws ClientProtocolException, IOException, SignatureException{String s = genHeaderParam(id, secret);System.out.println(s);}
}

好了,今天关于开放平台之接口认证鉴权就到这里。

欢迎大家点击下方卡片关注《coder练习生》

http://www.lryc.cn/news/44439.html

相关文章:

  • Vue自创插件发布到npm以及使用方法
  • 合成孔径雷达干涉测量InSAR数据处理、地形三维重建、形变信息提取、监测等实践技术
  • Java刷题,蓝桥杯省赛第十二届(第一场)4-------------6
  • Docker Cgroups——Docker 资源限制背后的技术原理
  • 十四. MySQL 锁相关
  • ModStartBlog v7.0.0 网站简单统计,支持博客分享
  • 【C语言蓝桥杯每日一题】—— 递增序列
  • node_express框架01
  • 想转行做程序员,该怎么选择开发语言?哪个岗位工资最高?
  • JavaWeb——【笔记】3.2JavaWeb_Web核心_Request(请求)+Response(响应)
  • HTML 标签和属性
  • MySQL 连接的使用
  • 配置案例丨EtherCAT转Profinet网关连接凯福科技总线步进驱动器
  • VSCODE连接ssh服务器时提示could not establish connection to解决方法
  • 网络安全之防火墙 双机热备实验
  • Java高频面试题(2023最新整理)
  • mongoDB学习笔记
  • 快速融人,融资的共享模式,实体,线上皆可参考
  • 纯干货版阿里巴巴国际站入门攻略
  • jQuery四、其他方法
  • 2023年先进无人飞行系统国际会议(ICAUAS 2023) | IOP JPCS独立出版
  • 2022蓝桥杯省赛——修剪灌木
  • Spring Boot Aop初接触
  • 【创作赢红包】LeetCode:232. 用栈实现队列
  • Mybatis+Mysql 实现向下递归查询
  • python@调用系统命令行@os.system@subprocess@标准输入输出@sys.stdin@sys.stdout@input@print
  • 手握数据智能密钥,诸葛智能打开数字化经营“三重门”
  • C语言可以实现各种滤波算法
  • 使用Netty,当然也要了解它的连接闲置处理
  • 2、K-Planes