编写开放接口与思考

编写开放接口与思考

一、情景描述:

当一个项目开发一定程度时,会有跟合作厂商对接共同开发的情况,那么如果合作厂商想要使用你项目中的某个接口,你该如何把接口暴露给他们?

二、实现方式分析

1、因为现在接口大部分都需要携带token才能访问的,直接让这个接口免token访问是一种方式,也是最简单的方式,但是风险性太高,免token就相当于所有人都能够调用这个接口,不安全不推荐;

2、如果我们想要提供接口供别人调用,首先我们可以模仿市面上已有的提供对外接口的方式,站在巨人的肩膀上,让你更快一步

像市面上大部分的开放平台,都会提供很多开放的接口

也就不难猜出,如果要提供一个开放接口,在业务逻辑之上,要添加身份认证校验的功能
在这里插入图片描述

三、实现设计

结合已有的提供接口的方式,下面我来编写一个开放接口demo供大家参考

设计思路:

1、提供给调用者参数:appid,appkey
appid:身份id
appkey:公钥
解释:appid作为识别用户的标识,appkey公钥用来进行加密算法运算生成验证签名

2、加密规则:使用appid和appkey公钥+实时时间戳生成sign签名
3、使用方式:调用者使用appid和appkey公钥通过加密算法生成sign签名,然后把appid,sign,timestamp作为请求头来调用接口
timestamp:时间戳,如果超过范围则不允许调用接口
注意
1、既然要验证身份,那么创建身份也是需要由接口提供方来实现的;
2、创建好的身份信息建议入库保存;
3、为了保证时效性,添加timestamp参数;
只有三个参数都验证通过了,才能走接口业务代码

实现思路

1、验证appid

查询参数appid在数据库中是否存在,如果不存在则验证失败,如果存在则进入下一步

2、验证sign

查询参数sign是否满足自己要求的加密算法方式,如果不满足则sign比对不一致,如果满足则验签成功进入下一步

3、验证timestamp

查询timestamp是否在当前十分钟有效期内(时间要求可自定义),如果不满足则超时退出,满足则可进入业务层

四、代码实现

demo结构如下
在这里插入图片描述
controller层

@Slf4j
@RequestMapping("hello")
@RestController
public class HelloController {
    private static final long  diffMile = 900000;//15*60*1000毫秒=15分钟内有效
    @Value("${appsecret}")
    private String  appsecret;
    @Value("${appid}")
    private String  appid;
    @RequestMapping("/oneInterface")
    public Result oneInterface(HttpServletRequest request) {

        Result ret = new Result();
        String timestamp = request.getHeader("timestamp");
        String checkappid = request.getHeader("appid");
        String sign = request.getHeader("sign");
        if (checkappid == null || timestamp == null || sign == null) {
            log.info("请求参数缺少");
            return ret.fail("请求参数缺少");
        }
        if (!appid.equals(checkappid)) {//校验appid
            log.info("请求appid不正确");
            return ret.fail("请求appid不正确");
        }
        long nowTime = System.currentTimeMillis();
        long reqTime;
        try {
            reqTime = Long.parseLong(timestamp);
        } catch (Exception e) {
            log.info("时间戳转换异常", e);
            return ret.fail("时间戳转换异常");
        }
        if (Math.abs(nowTime - reqTime) > diffMile ) {//差值绝对值大于区间
            log.info("与服务器时间相差超过15分钟");
            return ret.fail("与服务器时间相差超过15分钟");
        }
        //校验签名
        String checksign = MD5Util.MD5Encode(appid.concat(appsecret).concat(timestamp), "UTF-8");
        if (!sign.equals(checksign)) {
            log.info("签名不正确");
            return ret.fail("签名不正确");
        }
        log.info("校验成功");

        //业务逻辑
        return ret.ok("接口调用成功");
    }
}

加密工具类

package com.windwoo.utils;

import java.security.MessageDigest;


public class MD5Util {

    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();
    }


    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }


    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString
                        .getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString;
    }

    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
        "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}

上述代码使用的加密方式是对称加密,也就是提供者和使用者密钥appsecret是一样的

接口调试
在这里插入图片描述

在编写好接口后,还需要告诉调用者生成签名的方式,demo中实现方式是将appid,appsecret,timestamp字符串进行拼接然后md5加密

String sign = MD5Util.MD5Encode(appid.concat(appsecret).concat(timestamp), "UTF-8");

五、总结:

以上便是自定义开放接口全部步骤,当然校验的方式也有很多种,加密方式也有很多种,像对称加密,非对称加密,信息摘要,数字签名等,不同的加密算法对应着不同的应用场景,大家可以选择适合的方式来调整

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值