当前位置:   article > 正文

API安全接口安全设计_api接口安全设计

api接口安全设计

转载自: API安全接口安全设计_zhou920786312的博客-CSDN博客_接口安全

如何保证外网开放接口的安全性。

  1. 使用加签名方式,防止数据篡改
  2. 信息加密与密钥管理
  3. 搭建OAuth2.0认证授权
  4. 使用令牌方式
  5. 搭建网关实现黑名单和白名单

一令牌方式搭建搭建API开放平台

方案设计:

1第三方机构申请一个appId,通过appId去获取accessToken,每次请求获取accessToken都要把老的accessToken删掉

2第三方机构请求数据需要加上accessToken参数,每次业务处理中心执行业务前,先去dba持久层查看accessToken是否存在(可以把accessToken放到redis中,这样有个过期时间的效果),存在就说明这个机构是合法,无需要登录就可以请求业务数据。不存在说明这个机构是非法的,不返回业务数据。

3好处:无状态设计,每次请求保证都是在我们持久层保存的机构的请求,如果有人盗用我们accessToken,可以重新申请一个新的taken.

二基于OAuth2.0协议方式

 原理

第三方授权,原理和1的令牌方式一样

1.假设我是服务提供者A,我有开发接口,外部机构B请求A的接口必须申请自己的appid(B机构id)

2.当B要调用A接口查某个用户信息的时候,需要对应用户授权,告诉A,我愿同意把我的信息告诉B,A生产一个授权token给B。

3.B使用token获取某个用户的信息。

联合微信登录总体处理流程

1 :用户同意授权,获取code

2 :通过code换取网页授权access_token

3  :通过access_token获取用户openId

4  :通过openId获取用户信息

三信息加密与密钥管理

单向散列加密
对称加密
非对称加密
安全密钥管理

1单向散列加密
散列是信息的提炼,通常其长度要比信息小得多,且为一个固定长度。加密性强的散列一定是不可逆的,这就意味着通过散列结果,无法推出任何部分的原始信息。任何输入信息的变化,哪怕仅一位,都将导致散列结果的明显变化,这称之为雪崩效应。散列还应该是防冲突的,即找不出具有相同散列结果的两条信息。具有这些特性的散列结果就可以用于验证信息是否被修改。
单向散列函数一般用于产生消息摘要,密钥加密等,常见的有:
1、MD5(Message Digest Algorithm 5):是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。
2、SHA(Secure Hash Algorithm):可以对任意长度的数据运算生成一个160位的数值;
SHA-1与MD5的比较
因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
1、对强行供给的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2128数量级的操作,而对SHA-1则是2160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
2、对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3、速度:在相同的硬件上,SHA-1的运行速度比MD5慢。

1、特征:雪崩效应、定长输出和不可逆。
2、作用是:确保数据的完整性。
3、加密算法:md5(标准密钥长度128位)、sha1(标准密钥长度160位)、md4、CRC-32
4、加密工具:md5sum、sha1sum、openssl dgst。
5、计算某个文件的hash值,例如:md5sum/shalsum FileName,openssl dgst –md5/-sha

2对称加密

秘钥:加密解密使用同一个密钥、数据的机密性双向保证、加密效率高、适合加密于大数据大文件、加密强度不高(相对于非对称加密)

对称加密优缺点

 

优点:与公钥加密相比运算速度快。

缺点:不能作为身份验证,密钥发放困难

DES

是一种对称加密算法,加密和解密过程中,密钥长度都必须是8的倍数

  1. public class DES {
  2. public DES() {
  3. }
  4. // 测试
  5. public static void main(String args[]) throws Exception {
  6. // 待加密内容
  7. String str = "123456";
  8. // 密码,长度要是8的倍数 密钥随意定
  9. String password = "12345678";
  10. byte[] encrypt = encrypt(str.getBytes(), password);
  11. System.out.println("加密前:" +str);
  12. System.out.println("加密后:" + new String(encrypt));
  13. // 解密
  14. byte[] decrypt = decrypt(encrypt, password);
  15. System.out.println("解密后:" + new String(decrypt));
  16. }
  17. /**
  18. * 加密
  19. *
  20. * @param datasource
  21. * byte[]
  22. * @param password
  23. * String
  24. * @return byte[]
  25. */
  26. public static byte[] encrypt(byte[] datasource, String password) {
  27. try {
  28. SecureRandom random = new SecureRandom();
  29. DESKeySpec desKey = new DESKeySpec(password.getBytes());
  30. // 创建一个密匙工厂,然后用它把DESKeySpec转换成
  31. SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  32. SecretKey securekey = keyFactory.generateSecret(desKey);
  33. // Cipher对象实际完成加密操作
  34. Cipher cipher = Cipher.getInstance("DES");
  35. // 用密匙初始化Cipher对象,ENCRYPT_MODE用于将 Cipher 初始化为加密模式的常量
  36. cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
  37. // 现在,获取数据并加密
  38. // 正式执行加密操作
  39. return cipher.doFinal(datasource); // 按单部分操作加密或解密数据,或者结束一个多部分操作
  40. } catch (Throwable e) {
  41. e.printStackTrace();
  42. }
  43. return null;
  44. }
  45. /**
  46. * 解密
  47. *
  48. * @param src
  49. * byte[]
  50. * @param password
  51. * String
  52. * @return byte[]
  53. * @throws Exception
  54. */
  55. public static byte[] decrypt(byte[] src, String password) throws Exception {
  56. // DES算法要求有一个可信任的随机数源
  57. SecureRandom random = new SecureRandom();
  58. // 创建一个DESKeySpec对象
  59. DESKeySpec desKey = new DESKeySpec(password.getBytes());
  60. // 创建一个密匙工厂
  61. SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 返回实现指定转换的
  62. // Cipher
  63. // 对象
  64. // 将DESKeySpec对象转换成SecretKey对象
  65. SecretKey securekey = keyFactory.generateSecret(desKey);
  66. // Cipher对象实际完成解密操作
  67. Cipher cipher = Cipher.getInstance("DES");
  68. // 用密匙初始化Cipher对象
  69. cipher.init(Cipher.DECRYPT_MODE, securekey, random);
  70. // 真正开始解密操作
  71. return cipher.doFinal(src);
  72. }
  73. }
  74. 输出
  75. 加密前:123456
  76. 加密后:>p.72|
  77. 解密后:123456

3非对称加密

非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。

公钥与私钥是一对

公钥对数据进行加密,只有用对应的私钥才能解密
私钥对数据进行加密,只有用对应的公钥才能解密
过程:

甲方生成一对密钥,并将公钥公开,乙方使用该甲方的公钥对机密信息进行加密后再发送给甲方;
甲方用自己私钥对加密后的信息进行解密。
甲方想要回复乙方时,使用乙方的公钥对数据进行加密
乙方使用自己的私钥来进行解密。
甲方只能用其私钥解密由其公钥加密后的任何信息。

特点:

算法强度复杂

保密性比较好

加密解密速度没有对称加密解密的速度快。

对称密码体制中只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。所以保证其安全性就是保证密钥的安全,而非对称密钥体制有两种密钥,其中一个是公开的,这样就可以不需要像对称密码那样传输对方的密钥了。这样安全性就大了很多

适用于:金融,支付领域

RSA加密是一种非对称加密

  1. import javax.crypto.Cipher;
  2. import java.security.*;
  3. import java.security.interfaces.RSAPrivateKey;
  4. import java.security.interfaces.RSAPublicKey;
  5. import java.security.spec.PKCS8EncodedKeySpec;
  6. import java.security.spec.X509EncodedKeySpec;
  7. import java.security.KeyFactory;
  8. import java.security.KeyPair;
  9. import java.security.KeyPairGenerator;
  10. import java.security.PrivateKey;
  11. import java.security.PublicKey;
  12. import org.apache.commons.codec.binary.Base64;
  13. /**
  14. * RSA加解密工具类
  15. *
  16. *
  17. */
  18. public class RSAUtil {
  19. public static String publicKey; // 公钥
  20. public static String privateKey; // 私钥
  21. /**
  22. * 生成公钥和私钥
  23. */
  24. public static void generateKey() {
  25. // 1.初始化秘钥
  26. KeyPairGenerator keyPairGenerator;
  27. try {
  28. keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  29. SecureRandom sr = new SecureRandom(); // 随机数生成器
  30. keyPairGenerator.initialize(512, sr); // 设置512位长的秘钥
  31. KeyPair keyPair = keyPairGenerator.generateKeyPair(); // 开始创建
  32. RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
  33. RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
  34. // 进行转码
  35. publicKey = Base64.encodeBase64String(rsaPublicKey.getEncoded());
  36. // 进行转码
  37. privateKey = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
  38. } catch (NoSuchAlgorithmException e) {
  39. // TODO Auto-generated catch block
  40. e.printStackTrace();
  41. }
  42. }
  43. /**
  44. * 私钥匙加密或解密
  45. *
  46. * @param content
  47. * @param privateKeyStr
  48. * @return
  49. */
  50. public static String encryptByprivateKey(String content, String privateKeyStr, int opmode) {
  51. // 私钥要用PKCS8进行处理
  52. PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyStr));
  53. KeyFactory keyFactory;
  54. PrivateKey privateKey;
  55. Cipher cipher;
  56. byte[] result;
  57. String text = null;
  58. try {
  59. keyFactory = KeyFactory.getInstance("RSA");
  60. // 还原Key对象
  61. privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
  62. cipher = Cipher.getInstance("RSA");
  63. cipher.init(opmode, privateKey);
  64. if (opmode == Cipher.ENCRYPT_MODE) { // 加密
  65. result = cipher.doFinal(content.getBytes());
  66. text = Base64.encodeBase64String(result);
  67. } else if (opmode == Cipher.DECRYPT_MODE) { // 解密
  68. result = cipher.doFinal(Base64.decodeBase64(content));
  69. text = new String(result, "UTF-8");
  70. }
  71. } catch (Exception e) {
  72. // TODO Auto-generated catch block
  73. e.printStackTrace();
  74. }
  75. return text;
  76. }
  77. /**
  78. * 公钥匙加密或解密
  79. *
  80. * @param content
  81. * @param privateKeyStr
  82. * @return
  83. */
  84. public static String encryptByPublicKey(String content, String publicKeyStr, int opmode) {
  85. // 公钥要用X509进行处理
  86. X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyStr));
  87. KeyFactory keyFactory;
  88. PublicKey publicKey;
  89. Cipher cipher;
  90. byte[] result;
  91. String text = null;
  92. try {
  93. keyFactory = KeyFactory.getInstance("RSA");
  94. // 还原Key对象
  95. publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
  96. cipher = Cipher.getInstance("RSA");
  97. cipher.init(opmode, publicKey);
  98. if (opmode == Cipher.ENCRYPT_MODE) { // 加密
  99. result = cipher.doFinal(content.getBytes());
  100. text = Base64.encodeBase64String(result);
  101. } else if (opmode == Cipher.DECRYPT_MODE) { // 解密
  102. result = cipher.doFinal(Base64.decodeBase64(content));
  103. text = new String(result, "UTF-8");
  104. }
  105. } catch (Exception e) {
  106. // TODO Auto-generated catch block
  107. e.printStackTrace();
  108. }
  109. return text;
  110. }
  111. // 测试方法
  112. public static void main(String[] args) {
  113. /**
  114. * 注意: 私钥加密必须公钥解密 公钥加密必须私钥解密
  115. * // 正常在开发中的时候,后端开发人员生成好密钥对,服务器端保存私钥 客户端保存公钥
  116. */
  117. System.out.println("-------------生成两对秘钥,分别发送方和接收方保管-------------");
  118. RSAUtil.generateKey();
  119. System.out.println("公钥:" + RSAUtil.publicKey);
  120. System.out.println("私钥:" + RSAUtil.privateKey);
  121. System.out.println("-------------私钥加密公钥解密-------------");
  122. String textsr = "11111111";
  123. // 私钥加密
  124. String cipherText = RSAUtil.encryptByprivateKey(textsr,
  125. RSAUtil.privateKey, Cipher.ENCRYPT_MODE);
  126. System.out.println("私钥加密后:" + cipherText);
  127. // 公钥解密
  128. String text = RSAUtil.encryptByPublicKey(cipherText,
  129. RSAUtil.publicKey, Cipher.DECRYPT_MODE);
  130. System.out.println("公钥解密后:" + text);
  131. System.out.println("-------------公钥加密私钥解密-------------");
  132. // 公钥加密
  133. String textsr2 = "222222";
  134. String cipherText2 = RSAUtil.encryptByPublicKey(textsr2, RSAUtil.publicKey, Cipher.ENCRYPT_MODE);
  135. System.out.println("公钥加密后:" + cipherText2);
  136. // 私钥解密
  137. String text2 = RSAUtil.encryptByprivateKey(cipherText2, RSAUtil.privateKey, Cipher.DECRYPT_MODE);
  138. System.out.print("私钥解密后:" + text2 );
  139. }
  140. }

四使用加签名方式,防止数据篡改

  1. 客户端:请求的数据分为2部分(业务参数,签名参数),签名参数=md5(业务参数)
  2. 服务端: 验证md5(业务参数)是否与签名参数相同

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/853775
推荐阅读
相关标签
  

闽ICP备14008679号