记录一个对外接口签名问题
场景:
一,本公司一个项目支付中心,需要和另外一个系统oracle进行交互
流程是:支付中心推送数据到oracle系统,oracle系统再推送返回结果到支付中心
前者是:调用oracle接口,webservice实现
后者是:支付中心对外暴露一个restful接口,供oracle调用
因为项目发布到公网,别人如果拿到url可参数就可以直接调用接口,存在风险
怎么解决:就是调用者需要签名,校验权限
方式1,
/*** 校验 Authorization* 前后端都生成** @param request* @return*/
private static final String BASICAUTH = "AN_JI:AJ_1113";public static Boolean checkAuthorization(HttpServletRequest request) {String header = request.getHeader("Authorization");byte[] encodeBase = Base64.encodeBase64(BASICAUTH.getBytes());String authorization = new String(encodeBase);authorization = "Basic " + authorization;return authorization.equals(header); }
具体实现为:和调用方(前端)约定一个值,BASICAUTH,第三方和我方约定对该值进行base64编码处理,第三方调用时把编码后的值传过来,放到请求头中,我方取到该值进行校验,有且一致,则调用,否则没有权限。
缺点:
试想如果黑客拿到这个编码后的值,直接传到后台,我方可以调用通过,就可以随便调用我们的接口了。
场景:
二,开放平台,三个角色,平台,服务提供方,第三方调用者
服务方把接口放到平台,第三方调用者接入平台,然后通过平台调用服务提供方接口。还是类似上面的问题,需要签名。
先考虑一下,存在什么风险
1,服务提供方接口放到平台,参数是固定的,如果别人改了参数,调用接口,这样就不行了。
2,第三方不改接口参数,如果这个调用者没有接入平台,他是不能调的,即需要身份验证
再看怎么实现:流程如下
1,第三方调用方和平台约定签名规则,如下
2,第三方调用方选择平台中已上线的接口,生成签名sign和请求url
3,第三方通过url(这个url中包含签名sign,就是校验位),调用平台接口
4,平台验签,是由网关做的,就是同样的签名规则,再生成一个签名,比较url中第三方传过来的签名,一直则验签通过
5,身份验证,是校验url中,应用appId存在
参数说明:
开放平台API请求参数分为两种:系统参数和业务参数
系统参数:访问开放平台必须要传的参数,包括应用appId,接口名称method、应用签名sign和时间戳timestamp
业务参数:是由接口提供商指定,调用方访问接口时必须传接口指定的参数,详情参考接口列表
签名规则:
签名sign是通过应用在平台的私钥和请求参数根据一定算法生成的签名值,主要是防止参数在传输过程中被篡改, 同时对调用方的身份进行校验
签名生成步骤:
第1步:
将除签名sign外的所有请求参数按参数名首字母进行升序排序,其中参数包括系统参数和业务参数
第2步:
将第1步得到的排序结果,依次按照"keyvalue"的形式拼接成待加密的串
第3步
对第2步得到的新串进行HMAC加密并转化为大写的十六进制签名串
签名示例如下:
假设请求为:/anji-open/open-api/request?appId=testApp&method=testApp&sign=8D45C66B6E1E773614E5866541EAF78D×tamp=111&name=hello&password=123456&age=12
1、关键信息: 应用私钥:29bca37bf0174ea287a770cd0d4ff83c 请求参数:appId=testApp&method=testApp&sign=8D45C66B6E1E773614E5866541EAF78D×tamp=111&name=hello&password=123456&age=122、将除"sign"外所有的参数进行排序:age、appId、method、name、password、timestamp; 依次按照"keyvalue"形式拼接的结果:age12appIdtestAppmethodtestAppnamehellopassword123456timestamp1113、将得到的新串进行HMAC加密并转化为大写的十六进制签名串:8D45C66B6E1E773614E5866541EAF78D
实现:
*** 验证签名,防止数据被篡改* @author lr* @since 2019-05-29 17:02*/ public class SignUtils {private final static String SIGN_PARAM="sign";/*** 生产签名* @param params* @param secret* @return* @throws IOException*/public static String generateSign(Map<String, String> params, String secret) throws IOException {// 第一步:检查参数是否已经排序String[] keys = params.keySet().toArray(new String[0]);Arrays.sort(keys);// 第二步:把所有参数名和参数值串在一起StringBuilder query = new StringBuilder();for (String key : keys) {//跳过参数"sign",sign不参与签名if(StringUtils.equals(SIGN_PARAM,key)) {continue;}String value = params.get(key);if (StringUtils.isNotBlank(value)) {query.append(key).append(value);}}// 第三步:使用HMAC加密byte[] bytes = encryptHMAC(query.toString(), secret);// 第四步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串,此方法需要时使用)return byte2hex(bytes);}/*** 加密* @param data* @param secret* @return* @throws IOException*/public static byte[] encryptHMAC(String data, String secret) throws IOException {byte[] bytes = null;try {SecretKey secretKey = new SecretKeySpec(secret.getBytes(ApiConstants.CHARSET_UTF8), "HmacMD5");Mac mac = Mac.getInstance(secretKey.getAlgorithm());mac.init(secretKey);bytes = mac.doFinal(data.getBytes(ApiConstants.CHARSET_UTF8));} catch (GeneralSecurityException gse) {throw new IOException(gse.toString());}return bytes;}/*** 转16进制* @param bytes* @return*/public static String byte2hex(byte[] bytes) {StringBuilder sign = new StringBuilder();for (int i = 0; i < bytes.length; i++) {String hex = Integer.toHexString(bytes[i] & 0xFF);if (hex.length() == 1) {sign.append("0");}sign.append(hex.toUpperCase());}return sign.toString();}public static void main(String[] args) {Map<String,String> map = new HashMap<>(16);map.put("appId","testApp");map.put("method","testPost");map.put("timestamp","111");try {String s = generateSign(map, "e113e43bb76a437d94848a2bbbb45b0b");System.out.println(s);} catch (IOException e) {e.printStackTrace();}} }
三,公积金项目
流程:
调公积金接口,需要验证签名,签名规则MD5 apiKey
系统入参:apiKey timestamp sign
盐:appSecret
记录一个对外接口签名问题相关推荐
- 你连对外接口签名都不会知道?有时间还是要学习学习。
背景 周三,18:00. 小明扭了扭微微发酸的脖子,揉了揉盯着屏幕有些干涩的眼睛. 终于忙完了,临近下班,整个人心也变得放松起来. "对接方需要我们提供新的服务,下周二上线,需求我发你了,很 ...
- 复习Java第一个项目学生信息管理系统 01(界面部分) Java面试题抽象类和接口生活【记录一个咸鱼大学生三个月的奋进生活】013
记录一个咸鱼大学生三个月的奋进生活013 复习Java(学生信息管理系统01界面部分) 设置背景(WelcomePanel)类 登录界面(LoginFrame)类 主界面(MainFrame)类 学习 ...
- 探讨一下常见支付系统的对外接口
作为一个具备用户交易能力的网站,丰富它的支付渠道对于获客和提高日活都 有不可估量的积极作用.算起来,我接触过的支付系统也有几十个了,在这里总结一下我所接触过的支付系统对外接口的设计方案. 1. 支付宝 ...
- Effective C# 原则22:用事件定义对外接口(译)
Effective C# 原则22:用事件定义对外接口 Item 22: Define Outgoing Interfaces with Events 可以用事件给你的类型定义一些外部接口.事件是基于 ...
- Java简单的对外接口验签
对外接口,需要校验一下是否有相应权限,简单的一个小代码. res加密util: /*** @description: AES加密解密工具* @author:mic* @create: **/ publ ...
- php支付接口签名,php实现支付接口签名验证
前言 游戏服务器的玩家充值流程,如果通过google商店或者app store进行充值的话,需要实现回调支付地址.玩家充值成功以后,app store或者google商店会向回调地址传递参数,验证玩家 ...
- 人人都是接口开发大师,这个开源项目花5分钟就可以开发一个API接口
PhalApi开源接口框架 读音:派框架,官网:https://www.phalapi.net/ PhalApi是一个PHP轻量级开源接口框架,致力于快速开发接口服务.支持HTTP/SOAP/RPC等 ...
- 软件测试 接口测试 接口鉴权 token鉴权 Mock Server 接口加解密 接口签名sign
文章目录 1 接口鉴权 1.1 cookie鉴权 1.2 session鉴权 1.3 token鉴权 1.4 Postman的鉴权方式 2 Mock Server 3 接口加解密 3.1 加密方式 3 ...
- 微信与财付通接口签名调试总结
博客原文 传送门:t.hengwei.me 微信与财付通接口签名调试总结 这几年国内互联网的迅速发展不仅催生出了BAT,也使得第三方支付平台异军突起.在欧美还是信用卡统治的时代,另一个具有中国特色的第 ...
- 接口签名中的三位小伙伴signature,nonce,timestamp
在请求一些开放平台的接口时,我们一般会在请求头中塞入一些签名相关的信息以证明身份.以微信API-V3的为例,请求头中包含的认证信息主要包含: signature(签名值) nonce(随机串) tim ...
最新文章
- 140万!香港大学设高额博士奖学金
- (转)HLSL,函数列表
- OSI各层相关的协议
- php mysql 查询缓存_mysql 查询缓存使用详解
- PhoneGap学习笔记(一) 框架搭建
- python3.8版本支持flask-sqlalchey包吗_python3中使用flask_sqlalchemy的几个问题
- 用python turtle画龙猫_【跟着弹簧学画画】教你一步步画出一只超萌的龙猫来!...
- vux安装中遇到的坑(转)
- C++的STL标准库学习(vector)
- 打造linux回收站功能
- 最牛通达信短线超强波段主图指标公式 源码
- “2021年度全球十大人工智能治理事件”:数据、算法、伦理受关注,AI发展需治理同行
- android日记功能的实现6,我的android studio学习日记
- win10退出微软账号
- SOC上的总线真的是总线?
- oracle缓存文件,oracle的缓存
- 电信:自娱自乐的全员揽装,让人心寒!
- 织梦CMS系统正式收费:5800元 站长们真的慌了
- 计算机资料室英语翻译,资料英文怎么说_资料的英文怎么写 - 沪江英语
- opencv 图片处理之 png 转 jpg