高级鉴权网关设计二:SM2国密+协议SPI可扩展+动态配置

​ 上一篇文章是定义切面来做鉴权,针对接口时使用比较方便,还有一种是网关的鉴权如何处理?下面为大家介绍一种比较常用的方案,附带可扩展设计

​ 既然是网关其实就是和外部的礼尚往来,每个第三方还有可能不一样,一般常用的有http的form表单,get,post,https,和每个第三方的交互签名方式、加密方式都可能不同,很多时候取决于你是甲方爸爸还是乙方儿子,如果是甲方就好了,对接就按你们的来,你们来对我们,乙方就痛苦了,得适配不同的甲方爸爸,那我们该如何设计呢?

简单框架如下,提取抽象出业务节点(加密签名可有可无)
请添加图片描述

重点来了,我们可以根据channelType定义多套流程,

  1. 一个是simple简单扩展,驼峰下划线可支持转化
  2. 一个是normal常规扩展,定义公共参数,比如appid,version,sign,timestamp等等;支持驼峰转下划线,也可以支持更多
  3. 一个是个性化,一般按甲方的来很容易这样,可以定义多个个性化type,组装不同的甲方需要的个性化参数

关于加密和协议根据两个维度进行扩展,一个是加密类型encryptType,一个是协议类型protocolType,分别定义好枚举

动态配置是什么,就是配置上面我需要走哪条道所需要的配置,比如要配置encryptType=SM2,protocolType=https,channelType=simple,秘钥,域名等等

请添加图片描述

上面是完善后的流程,相对不是很难,重点在于考虑好扩展

关于加密以及签名sign,我们和外部如何友好的通信但是又不能把秘钥暴露给对方?给大家介绍一下

以SM2非对称加密为例,我们和外部都定义一套公钥私钥,分别把公钥给到对方

调用外部接口时,我们用外部给的的公钥加密,用我们的私钥加签。
外部收到请求后,使用我们的公钥验签,用外部自己的私钥解密。
然后外部将返回结果用我们的公钥加密,外部的私钥加签。我们使用外部的公钥验签,使用私钥解密。

这样保证了我们的私钥都在自己手里,实现了数据加密,并生成了sign保证了安全性

给大家附上SM2国密工具

@Slf4j
public class SM2Util {
    @Data
    public static class CryptoKey {
        public String key;
        public String VerKey;
    }

    /**
     * 创建密钥对
     */
    public static CryptoKey createKey() {
        SM2Key sm2 = new SM2Key();
        sm2.generateKey();
        String key = ByteUtil.byte2hex(sm2.getPrivKeyBytes());
        String verkey = ByteUtil.byte2hex(sm2.getPubKey()).substring(2);
        CryptoKey cryptoKey = new CryptoKey();
        cryptoKey.setKey(key);
        cryptoKey.setVerKey(verkey);
        return cryptoKey;
    }

    /**
     * 加签
     */
    public static String sign(String key, String messageRaw) {
        try {
            byte[] msgHash = HashUtil.sha256(messageRaw.getBytes());
            BigInteger privKey = new BigInteger(key, 16);
            SM2Key sM2Key = SM2Key.fromPrivate(privKey);
            String rawData = sM2Key.sign(msgHash).toBase64();
            return rawData;
        } catch (Exception e) {
            log.error("sm2 sign error ", e);
            return null;
        }
    }

    /**
     * 校验
     */
    public static boolean verify(String verkey, String messageRaw, String signatureRaw) {
        try {
            byte[] signedBytes = Base64.getDecoder().decode(signatureRaw);
            byte[] msgHash = HashUtil.sha256(messageRaw.getBytes());
            byte[] pkBytes = SM2Key.recoverPubBytesFromSignature(signedBytes, msgHash).getEncoded(false);
            String pk = ByteUtil.byte2hex(pkBytes).substring(2);
            if (verkey.equals(pk)) {
                return true;
            } else {
                return false;
            }
        }catch (Exception e){
            log.error("sm2 verify error ", e);
            return false;
        }
    }

    /**
     * 加密
     */
    public static String crypt(String verkey, String messageData) {
        try {
            byte[] rawBytes = SM2Key.encryptWithRandomKey(messageData.getBytes(), verkey);
            String rawData = ByteUtil.byte2hex(rawBytes);
            return rawData;
        }catch (Exception e){
            log.error("sm2 crypt error ", e);
            return null;
        }
    }

    /**
     * 解密
     */
    public static String decrypt(String key, String encryptedMessage)  {
        BigInteger privKey = new BigInteger(key, 16);
        SM2Key sM2Key = SM2Key.fromPrivate(privKey);
        byte[] rawData = ByteUtil.hex2byte(encryptedMessage);
        try {
            byte[] messageDataBytes = sM2Key.decryptWithRandomKey(rawData);
            String messageData = new String(messageDataBytes);
            return messageData;
        }catch (Exception e){
            log.error("sm2 decrypt error ", e);
            return null;
        }
    }
}
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我是小酒

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

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

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

打赏作者

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

抵扣说明:

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

余额充值