写点什么

2021,你还在写“赤裸裸”的 API 吗?

  • 2021 年 11 月 10 日
  • 本文字数:2252 字

    阅读完需:约 7 分钟

  • @param secretKey

  • @return

  • @throws Excep


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


tion


*/


public static byte[] decrypt(byte[] src, String secretKey) throws Exception {


// DES 算法要求有一个可信任的随机数源


SecureRandom random = new SecureRandom();


// 创建一个 DESKeySpec 对象


DESKeySpec desKey = new DESKeySpec(secretKey.getBytes());


// 创建一个密匙工厂,返回实现指定转换的


SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");


// 将 DESKeySpec 对象转换成 SecretKey 对象


SecretKey secureKey1 = keyFactory.generateSecret(desKey);


// 获取 Cipher 对象


Cipher cipher = Cipher.getInstance("DES");


// 初始化 Cipher 对象


cipher.init(Cipher.DECRYPT_MODE, secureKey1, random);


// 解密


return cipher.doFinal(src);


}


复制代码


接下来我们测试下


public static void main(String[] args) throws Exception {


// 待加密内容


String str = "https://juejin.cn/user/2084329778071479";


// 密钥


String secretKey = "xtianyaa";


byte[] encrypt = encrypt(str.getBytes(), secretKey);


System.out.println("加密前:" +str);


System.out.println("加密后:" + new String(encrypt));


// 解密


byte[] decrypt = decrypt(encrypt, secretKey);


System.out.println("解密后:" + new String(decrypt));


}


复制代码


输出结果


加密前:https://juejin.cn/user/2084329778071479


加密后:SA(??j?tj??G?/?[M(??y??t.?7z"D?3?<


解密后:https://juejin.cn/user/2084329778071479


复制代码


2、非对称加密




非对称加密算法需要两个密钥:公钥私钥。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。 非对称加密算法实现机密信息交换的基本过程是:甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方;甲方再用自己私钥对加密后的信息进行解密。甲方想要回复乙方时正好相反,使用乙方的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密。我们看下非对称加密和对称加密的区别



非对称密码体制的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加密解密速度没有对称加密解密的速度快。对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多。


关于非对称加密的实现算法主要有:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法),使用最广泛的是RSA算法。


如何证明你是你


=======


关于 API 接口另一个重要的部分就是签名,通过签名,才知道接口的调用方有没有被进行篡改。下面一起看下接口签名的实现


/**


  • @param appId 调用方的 ID,唯一

  • @param appKey 调用方 APP_KEY,每个调用方固定一个字符串,唯一

  • @param sign 签名,appId+appKey + request 秘钥(不参与接口参数传递,本地保存) + 时间戳(以 long 类型的字符串.格式:yyyyMMddHHmmss),经过 MD5 加密后生成的串(字母小写)

  • @param requestTime 时间戳(以 long 类型的字符串)

  • @param type 数据类型

  • @param data 数据内容 使用非对称加密,接口调用者用公钥加密,接收后用私钥进行解密

  • @return


*/


@PostMapping("/system_api")


@Limit(key = "get_system_api", period = 60, count = 10, name = "主屏接口数据采集", prefix = "limit")


public String systemApi(@RequestHeader("APP_ID") String appId,


@RequestHeader("APP_KEY") String appKey,


@RequestHeader("TOKEN") String sign,


@RequestHeader("TIMESTAMP") String requestTime,


@RequestParam String type, @RequestBody String data){


String checkInfo = paramsCheck(appId,appKey,sign,requestTime);


if(!SUCCESS.equals(checkInfo)){


return checkInfo;


}


return SUCCESS;


}


复制代码


可以看到,其中 sign 通过 appId+appKey + request 秘钥+ 时间戳,经过 MD5 加密后生成,当我们拿到这个 sign 时,再根据对应的参数进行验证


**


  • 根据接口请求的参数进行身份验证

  • @param appId

  • @param appKey

  • @param sign

  • @param requestTime


*/


private String paramsCheck(String appId, String appKey, String sign, String requestTime) {


AppConfig appConfig = appConfigService.getAppConfig(appId);


String errorInfo = SUCCESS;


//1、判断 key 是否正确


if (!appKey.equals(appConfig.getAppKey())){


errorInfo = "500";


}


//2、拼接字符串


String key = appId+appConfig.getAppKey()+appConfig.getAppSecret()+requestTime;


//3、根据 appId+appKey+AppSecret+requestTime,经过 md5 后, 生成签名


String newSign = DigestUtils.md5DigestAsHex(key.getBytes());


//4、判断签名是否经过篡改


if(!sign.equals(newSign)){


errorInfo = "500";


}


//5、判断请求时间是否异常,防止使用过期签名进行身份认证


Date date = null;


try {


date = new SimpleDateFormat("yyyyMMddHHmmss").parse(requestTime);


} catch (ParseException e) {


log.error(e.getMessage());


}


long second = 0;


if (date != null) {


second = getDatePoor(new Date(),date);


}else{


errorInfo = "TIME IS NULL";


}


if(second>TIME_OUT){


errorInfo = "TIME OUT";


}


return errorInfo;


}


复制代码

评论

发布
暂无评论
2021,你还在写“赤裸裸”的API吗?