springboot项目前后端实现AES加解密

发布时间:2023年12月20日

后端代码如下:

1、EncryptionUtils? 这是加解密工具类

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

/**
 * @ClassName EncryptionUtils
 * @Description: TODO
 * @Author LRH
 * @Date 2023/12/14
 * @Version V1.0
 **/
public class EncryptionUtils {
    /**
     * Description: 配合前端CryptoJS实现加密、解密工作。
     * CryptoJS 是一个 JavaScript 库,提供了一系列密码学函数和工具,用于加密、解密、生成摘要等任务。
     * 它支持多种加密算法,包括常见的对称加密算法(如 AES、DES)和非对称加密算法(如 RSA)。
     */


        private final static String IV = "67890123456";//需要前端与后端配置一致
        private final static String KEY = "1234567890123456";

        /**
         * 加密算法,使用默认的IV、KEY
         * @param content
         * @return
         */
        public static String encrypt(String content){
            return encrypt(content,KEY,IV);
        }

        /**
         * 解密算法,使用默认的IV、KEY
         * @param content
         * @return
         */
        public static String decrypt(String content){
            return decrypt(content,KEY,IV);
        }
        /**
         * 加密方法
         * @param content
         * @param key
         * @param iv
         * @return
         */
        public static String encrypt(String content, String key, String iv){
            try{
                // "算法/模式/补码方式"NoPadding PkcsPadding
                Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
                int blockSize = cipher.getBlockSize();
                byte[] dataBytes = content.getBytes();
                int plaintextLength = dataBytes.length;
                if (plaintextLength % blockSize != 0) {
                    plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
                }
                byte[] plaintext = new byte[plaintextLength];
                System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
                SecretKeySpec keyspec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
                IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes("UTF-8"));
                cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
                byte[] encrypted = cipher.doFinal(plaintext);
                return Base64.getEncoder().encodeToString(encrypted);
            }catch (Exception e) {
                throw new RuntimeException("加密算法异常 CryptoUtil encrypt()加密方法,异常信息:" + e.getMessage());
            }
        }

        /**
         * 解密方法
         * @param content
         * @param key
         * @param iv
         * @return
         */
        public static String decrypt(String content, String key, String iv){
            try {
                byte[] encrypted1 = Base64.getDecoder().decode(content);
                Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
                SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
                IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
                cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                byte[] original = cipher.doFinal(encrypted1);
                return new String(original).trim();
            } catch (Exception e) {
                throw new RuntimeException("加密算法异常 CryptoUtil decrypt()解密方法,异常信息:" + e.getMessage());
            }
        }

    public static void main(String[] args) {
        String str = "98B197CA526C5B2749F305DDB34233F7B8F4F9C09F83FEA6B6A2D98FFAE05A64";
        System.out.println(decrypt(str));
        }
    }

2、解码处理类DecodeInputMessage

/**
 * 解码处理
 * @author rstyro
 */
@Slf4j
public class DecodeInputMessage implements HttpInputMessage {

    private HttpHeaders headers;

    private InputStream body;

    public DecodeInputMessage(HttpInputMessage httpInputMessage) {

        try {

            // 2、从inputStreamReader 得到aes 加密的内容
            String encodeAesContent = new BufferedReader(new InputStreamReader(httpInputMessage.getBody())).lines().collect(Collectors.joining(System.lineSeparator()));
            JSONObject jsonObject = JSON.parseObject(encodeAesContent);
            // 3、AES通过密钥CBC解码
            String str = jsonObject.getString("data");
            String aesDecode = EncryptionUtils.decrypt(str);
            if (!StringUtils.isEmpty(aesDecode)) {
                // 4、重新写入到controller
                this.body = new ByteArrayInputStream(aesDecode.getBytes());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public InputStream getBody() throws IOException {
        return body;
    }

    @Override
    public HttpHeaders getHeaders() {
        return headers;
    }
}

3、控制器监听EncryptRequestAdvice类
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.IOException;
import java.lang.reflect.Type;

/**
 * 请求参数到controller之前的处理
 * @author rstyro
 */
@ControllerAdvice(basePackages = {"shengyun.controller"})
public class EncryptRequestAdvice implements RequestBodyAdvice {


    @Override
    public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
            return new DecodeInputMessage(httpInputMessage);
    }

    @Override
    public Object afterBodyRead(Object obj, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        // 这里就是已经读取到body了,obj就是
        return obj;
    }

    @Override
    public Object handleEmptyBody(Object obj, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
        // body 为空的时候调用
        return obj;
    }

}

4、结果返回工具类
?

public class ResultUtil {
    private static Logger logger = LoggerFactory.getLogger(ResultUtil.class);
    public static ResultVO<Object> success(Object object) {
        ResultVO<Object> resultVO = new ResultVO<>();
        if(object instanceof String){
            resultVO.setData(object);
        }else {
            // 配置项
            SerializerFeature feature = SerializerFeature.WriteDateUseDateFormat;
            resultVO.setData(EncryptionUtils.encrypt(JSONObject.toJSONString(object,feature)));
        }
        resultVO.setCode(200);
        resultVO.setMsg("success");
        logger.info("返回参数:{}", JSONObject.toJSONString(resultVO));
        return resultVO;
    }

    public static ResultVO<Object> success() {
        return success(null);
    }
    public static ResultVO<Object> success(Object object, String msg) {
        ResultVO<Object> resultVO = new ResultVO<>();
        resultVO.setData(object);
        resultVO.setCode(200);
        resultVO.setMsg(msg);
        return resultVO;
    }
    public static ResultVO<Object> error(Integer status, String msg) {
        ResultVO<Object> resultVO = new ResultVO<>();
        resultVO.setCode(status);
        resultVO.setMsg(msg);
        return resultVO;
    }
}
5、接口返回实体类
@Data
public class ResultVO<T> implements Serializable {
    private Integer code;
    private String msg;
    private T data;
}

前端引入import CryptoJS from '@/uni_modules/crypto-js'

// 密钥和偏移量
const key = 'your-key'
const iv = 'your-iv'


// 加密函数
const encrypt = (data) => {
? const keyBytes = CryptoJS.enc.Utf8.parse(key)
? const ivBytes = CryptoJS.enc.Utf8.parse(iv)
debugger
? const encrypted = CryptoJS.AES.encrypt(data, keyBytes, {
? ? iv: ivBytes,
? ? mode: CryptoJS.mode.CBC,
? ? padding: CryptoJS.pad.NoPadding,
? })

? return encrypted.toString()
}


// 解密函数
const decrypt = (encryptedData) => {
? const cipherText = CryptoJS.enc.Base64.parse(encryptedData);
? const keyBytes = CryptoJS.enc.Utf8.parse(key);
? const ivBytes = CryptoJS.enc.Utf8.parse(iv);

? const decipher = CryptoJS.AES.decrypt(
? ? {
? ? ? ciphertext: cipherText,
? ? },
? ? keyBytes,
? ? {
? ? ? iv: ivBytes,
? ? ? mode: CryptoJS.mode.CBC,
? ? ? padding: CryptoJS.pad.NoPadding,
? ? }
? );

? const decryptedData = CryptoJS.enc.Utf8.stringify(decipher);
? return decryptedData;
}

// GET请求
const get = (data = {}, options = {}) => {
?? ?options.showLoading = data.showLoading || true
?? ?options.url = data.url
?? ?options.method = 'GET'
?? ?options.data = encrypt(data.data)
?? ?return request(options)
}

// POST请求
const post = (data = {}, options = {}) => {
?? ?options.showLoading = data.showLoading || true
?? ?options.showMask = data.showMask || false
?? ?options.showErrorToast = data.showErrorToast!=1
?? ?options.isForm = data.isForm || false
?? ?options.url = data.url
?? ?options.method = 'POST'
?? ?options.data = encrypt(data.data)
?? ?return request(options)
}

文章来源:https://blog.csdn.net/wzwsq/article/details/135079263
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。