【造个轮子系列】之保证RESTful接口数据的安全(一)AES加密解密 您所在的位置:网站首页 API接口加密是什么 【造个轮子系列】之保证RESTful接口数据的安全(一)AES加密解密

【造个轮子系列】之保证RESTful接口数据的安全(一)AES加密解密

2024-06-02 07:11| 来源: 网络整理| 查看: 265

前言

前后端分离的开发模式下,API是暴露给客户端(浏览器)的。如果不做任何访问限制,那么任何人都可以访问,更严重的是,如果返回的数据是明文的,那么爬虫可能就特别喜欢了。所以,API不仅要做访问限制,还要做数据的加密。本篇暂时说一下数据的加密,只是一些个人见解。

一、统一数据返回格式

前后端分离的开发模式下,要进行统一异常处理,其中要统一数据的返回格式,具体方法可参考慕课网课程:Spring Boot进阶之Web进阶。首先,自定义一个返回类来包装数据。

public class ResultBean{ /** * @param code * @param msg * @param data */ public ResultBean(Integer code, String msg, T data) { this.code = code; this.msg = msg; this.data = data; } /** 错误码 */ protected Integer code; /** 提示信息 */ protected String msg; /** * 返回的具体内容 * 有默认的初始值——空字符串"", * 因为阿里巴巴的fastjson处理数据时,不允许存在内容为null的字段 */ protected Object data; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } @Override public String toString() { return "ResultBean [code=" + code + ", msg=" + msg + ", data=" + data + "]"; } }

这样就可以直接在controller层返回ResultBean这个类了,也可以在写一个工具类来进行构造这个类。

二、后台数据加密

我们这里不具体说怎么统一处理异常,重点是数据的加密和解密。java后台对数据加密,前端对数据解密。

import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; import org.springframework.util.StringUtils; import sun.misc.BASE64Decoder; public class AESEncryptAndDecrypt { /**默认加密秘钥,必须16位*/ private static final String DEFAULT_KEY = "123456asdfghjklm"; /*** 算法*/ private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding"; /** * aes解密 * @param encrypt 内容 * @return * @throws Exception */ public static String decryptByDefaultKey(String encrypt) throws Exception { return decrypt(encrypt, DEFAULT_KEY); } /** * aes加密 * @param content * @return * @throws Exception */ public static String encryptByDefaultKey(String content) throws Exception { return encrypt(content, DEFAULT_KEY); } /** * base 64 encode * @param bytes 待编码的byte[] * @return 编码后的base 64 code */ private static String base64Encode(byte[] bytes) { return Base64.encodeBase64String(bytes); } /** * base 64 decode * @param base64Code 待解码的base 64 code * @return 解码后的byte[] * @throws Exception */ private static byte[] base64Decode(String base64Code) throws Exception { return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code); } /** * AES加密 * @param content 待加密的内容 * @param encryptKey 加密密钥 * @return 加密后的byte[] * @throws Exception */ private static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); Cipher cipher = Cipher.getInstance(ALGORITHMSTR); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES")); return cipher.doFinal(content.getBytes("utf-8")); } /** * AES加密为base 64 code * @param content 待加密的内容 * @param encryptKey 加密密钥 * @return 加密后的base 64 code * @throws Exception */ public static String encrypt(String content, String encryptKey) throws Exception { return base64Encode(aesEncryptToBytes(content, encryptKey)); } /** * AES解密 * * @param encryptBytes 待解密的byte[] * @param decryptKey 解密密钥 * @return 解密后的 String * @throws Exception */ private static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); Cipher cipher = Cipher.getInstance(ALGORITHMSTR); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES")); byte[] decryptBytes = cipher.doFinal(encryptBytes); return new String(decryptBytes); } /** * 将base 64 code AES解密 * @param encryptStr 待解密的base 64 code * @param decryptKey 解密密钥 * @return 解密后的string * @throws Exception */ public static String decrypt(String encryptStr, String decryptKey) throws Exception { return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey); } }

我们使用这个工具类对数据进行加密,所以,我们就要修改一下ReasultBean里设置数据的方法。

public ResultBean(Integer code, String msg, T data) { this.code = code; this.msg = msg; String encrypt = null; try { encrypt = AESEncryptAndDecrypt.encryptByDefaultKey(data.toString()); } catch (Exception e) { e.printStackTrace(); } this.data = encrypt; } public void setData(Object data) { String encrypt = null; try { encrypt = AESEncryptAndDecrypt.encryptByDefaultKey(data.toString()); } catch (Exception e) { e.printStackTrace(); } this.data = encrypt; }

将数据加密后再设置值,这样返给前端的数据就是加密的了。

三、前端数据解密

我们首先要引入解密的js,我们使用的是crypto。

$(function(){ $.ajax({ type:"post", url:"http://localhost:8081/post", data:{ a:"你是谁啊??" }, success:function(res){ var data = JSON.parse( Decrypt('123456asdfghjklm',res.data)); console.log(data); } }) //解密 function Decrypt(keyStr,word){ var key = CryptoJS.enc.Utf8.parse(keyStr); var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}); return CryptoJS.enc.Utf8.stringify(decrypt).toString(); } })

先写一个解密的函数,当我们拿到数据后,对加密字符串进行解密就可以进行后续的其他操作了。

写在后面的话

本文只是一个小小的例子,也只是我个人的想法而已,并没有用在生产环境中。主要还是AES的加密和解密。稍微修改一下还是可以用在生产环境中的,不过要保证秘钥的安全,可以动态获取,然后设置秘钥的过期时间。  



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有