SpringBoot 实现对提供的接口进行 AES (加密,解密)

业务来源:

       最近工作中,领导要求给别的项目组的小伙伴提供几个接口,要求对接口的参数进行解密操作,然后对返回的数据进行加密操作。

       这时我想到了AES  

       AES 是对称加密算法,优点:加密速度快;缺点:如果秘钥丢失,就容易解密密文,安全性相对比较差。

代码案例:

请求参数格式:

{
 "appId": "queryLectureListByPage",
 "data": "eIVh49T2zKQrtcrhVi6BXcXljN4XFlZc9csQiyayIE1eYeIatVNc9gOTL6HHYj29arBEV3TXMVnQxGIR2EHMfICQz+Aq5ldGk0ys13Rgiqk="
}

响应的参数格式:

{
    "code": 200,
    "message": "ok",
    "data": "eHDl88EzrjfZzA179EN6s1dUPs10bWpSWRo2skyQf1+eO6x66ypDnVXoyB5wr6T62lmfVdwa3oK0ZFqnOzd3SW/DE6UaMPZtJovzFTpjxbzvnuwO3v9b3vEsA2nOUQEjEqbpzBrzEClNtL2tkSuoA7oJkTiH3ec6otwFFJZGbV93JW9+xvFkG3TObHIO6fdqlgNIDGbgs7TnwStc64suuH+H7Bt25pCggCq6yVv+Zx69/0Zprvu5s7Dma8NYy/N69cfWgj+06Ik5DXcJlzlZXKQLwwQHiHtleIum2dSF3HWE7ck212n/zn1WVVpGUFnevYCr7Gx/lHbkh/hIOifl8sDpkaISP2tO4kXDi1neUyCnrM7437rf/ZhLPBANkkIO40cZcjEGdrMNswAfZ6XxkBTBq3BMpnjulUbSPZXA6xwwdiaORv1Jx9yxpVBRuw5D4FHby+VPRAh3WP2VMptpzXYeJGBJXU/KvODrKy+tDb8Iq/PUESzECrrYVc/QwWVeBmNKOFyCtXTB486QWqUGbFvoWHnQUUh/taM8/GOYglWzCtziDntRxum2qruxuq23fnNknKGi3wJBzBSZj8kWw0NUx7RIaZcoqwbzmYx4H6h9D28ViAv/y4/nQGxKho3nlW5EVuk6+yQLadc1DSp4Ug=="
}

生成密钥:

package com.ly.cloud.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import com.alibaba.druid.util.Base64;
import org.apache.commons.codec.binary.Hex;

public class AESUtils {

	private static final String AES = "AES";
	private static final String UTF8 = "UTF-8";
	private static final String CIPHERALGORITHM = "AES/ECB/PKCS5Padding";
	private static final String Key = "9!#95hsup*&$1zq7";

	
	public static void main(String[] args) throws IOException {
        // wqkjejqwkejqwk  可随便输入字符串,生成对应的密钥
		String wqkjejqwkejqwk = encrypts("wqkjejqwkejqwk");
		System.out.println(wqkjejqwkejqwk);
	}


	/**
	 * 生成base 64 作为AES加密后的密钥
	 */
	public static  String encrypts(String content) {
		try {
			byte[] encodeFormat = Key.getBytes();
			SecretKeySpec key = new SecretKeySpec(encodeFormat, AES);
			// Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance(CIPHERALGORITHM);
			// 加密内容进行编码
			byte[] byteContent = content.getBytes(UTF8);
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.ENCRYPT_MODE, key);
			// 正式执行加密操作
			byte[] result = cipher.doFinal(byteContent);
			return Hex.encodeHexString(result);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
    
}

思路:

通过传入的appId然后去数据库中查询到对应的 唯一密钥。然后根据唯一密钥进行解析密文。然后转成将密文转成 我们需要的参数对象。

核心代码:
AES加密解密工具类:
package com.ly.cloud.util;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import com.alibaba.druid.util.Base64;
import org.apache.commons.codec.binary.Hex;

public class AESUtils {

	private static final String AES = "AES";
	private static final String UTF8 = "UTF-8";
	private static final String CIPHERALGORITHM = "AES/ECB/PKCS5Padding";
	private static final String Key = "9!#95hsup*&$1zq7";

	/**
	 * AES加密+Base64转码
	 * 
	 * @param data 明文(16进制)
	 * @param key  密钥
	 * @return
	 */
	public static String encrypt(String data, String key) {
		byte[] keyb = null;
		keyb = Base64.base64ToByteArray(key);
		SecretKeySpec sKeySpec = new SecretKeySpec(keyb, "AES");
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			e.printStackTrace();
		}
		try {
			cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		byte[] bjiamihou = null;
		String miwen = "";
		try {
			bjiamihou = cipher.doFinal(data.getBytes("utf-8"));
			// byte加密后
			miwen = Base64.byteArrayToBase64(bjiamihou);// 密文用base64加密
		} catch (IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
 
		return miwen;
	}
    
	/**
	 * Base64解码 + AES解码
	 * 
	 * @param data 密文 (16进制)
	 * @param key  密钥
	 * @return
	 */
	public static String decrypt(String data, String key){
		byte[] keyb = null;
		keyb = Base64.base64ToByteArray(key);
		byte[] miwen = Base64.base64ToByteArray(data);
		SecretKeySpec sKeySpec = new SecretKeySpec(keyb, "AES");
		Cipher cipher = null;
		try {
			cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			e.printStackTrace();
		}
		try {
			cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		byte[] bjiemihou = null;
		String mingwen = "";
		try {
			bjiemihou = cipher.doFinal(miwen);
			// byte加密后
			mingwen = new String(bjiemihou,"utf-8");
		} catch (IllegalBlockSizeException | BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return mingwen;
	}
	
	public static void main(String[] args) throws IOException {
		String name = "{\"userId\":\"179135\",\"keyword\":\"讲座副标题\",\"pageNum\":\"1\",\"pageSize\":\"10\"}";
//		String encrypt = encrypt(name, "qVkn2qNkkyAAF8PjQL/7GQ==");
//		String name = "{\"userId\":\"179135\",\"pageNum\":\"1\",\"pageSize\":\"20\"}";

//		String name1 = "{\"userId\":\"179135\",\"organizerId\":\"02020\"}";
		String name1 = "{\"pageNum\":\"1\",\"pageSize\":\"20\"}";

		String encrypt = encrypt(name, "8c5e186c9de8e9a628234522a794f45b0f");
		System.out.println(encrypt);
		System.out.println("---------");
		System.out.println(decrypt(encrypt,"8c5e186c9de8e9a628234522a794f45b0f"));


		String wqkjejqwkejqwk = encrypts("wqkjejqwkererjqwk");
		System.out.println(wqkjejqwkererjqwk);
	}


	/**
	 * 生成base 64 作为AES加密后的密钥
	 */
	public static  String encrypts(String content) {
		try {
			byte[] encodeFormat = Key.getBytes();
			SecretKeySpec key = new SecretKeySpec(encodeFormat, AES);
			// Cipher对象实际完成加密操作
			Cipher cipher = Cipher.getInstance(CIPHERALGORITHM);
			// 加密内容进行编码
			byte[] byteContent = content.getBytes(UTF8);
			// 用密匙初始化Cipher对象
			cipher.init(Cipher.ENCRYPT_MODE, key);
			// 正式执行加密操作
			byte[] result = cipher.doFinal(byteContent);
			return Hex.encodeHexString(result);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}


    // 加密 
    public static String dataToAES(String password,String data){
    	String hexStr = encrypt(data, password);
    	return hexStr;
    }
    
    // 解密
    public static String AESToData(String password, String data){
    	return decrypt(data, password);
    }
    
}
业务层核心代码: 
    @Override
    public String organizerList(LectureEncryptDto encrypt) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        //获取appid 对应的key值
        String key = checkParam(encrypt);

        // 解密参数  根据传入不同的 对象返回不同的对象
        MySubscribeDto subscribe = returnObject(MySubscribeDto.class, key, encrypt);

        //校验解密后参数是否为空
        checkPageParam(subscribe, "2");
        Page<MySubscribe> page = new Page<>(subscribe.getPageNum(), subscribe.getPageSize());
        PageDto<MySubscribe> pageDto = new PageDto<>();
        IPage<MySubscribe> pageData = lectureMapper.organizerList(page, subscribe.getUserId());
        pageDto.setTotal(pageData.getTotal());
        pageDto.setPages(pageData.getPages());
        pageDto.setPageSize(subscribe.getPageSize());
        pageDto.setPageNum(subscribe.getPageNum());
        pageDto.setList(pageData.getRecords());
        //加密
        String json = JSONUtil.toJsonStr(pageDto);
        return AESUtils.dataToAES(key, json);
    }

    /**
     * 根据传入的不同的对象,将他进行解密。然后返回
     */
    public static <T> T returnObject(Class<T> clazz, String key, LectureEncryptDto dto) {
        Gson gson = new Gson();
        String decryptedData = AESUtils.AESToData(key, dto.getData());
        if (StrUtil.isEmpty(decryptedData)) {
            throw new BusinessException("appId生成的data密钥有误");
        }
        return gson.fromJson(decryptedData, clazz);
    }



    /**
     * 检查appID 是否有效
     */
    public String checkParam(LectureEncryptDto dto) {
        // 根据他传的appid 去数据库里取出appid 对应的 key值,
        String key = lectureMapper.getAppIdKey(dto.getAppId());
        if (StrUtil.isEmpty(key)) {
            throw new BusinessException("appId有误,请重新输入");
        }
        return key;
    }


    /**
     * 检查分页-以及其它所需参数是否为空
     */
    public static void checkPageParam(Object objects, String key) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<?> clazz = objects.getClass();
        Method getPageSizeMethod = clazz.getMethod("getPageSize");
        Method getPageNumMethod = clazz.getMethod("getPageNum");
        Integer pageSize = (Integer) getPageSizeMethod.invoke(objects);
        Integer pageNum = (Integer) getPageNumMethod.invoke(objects);
        if (pageSize == null || pageNum == null) {
            throw new BusinessException("页码不能为空");
        }
        // 根据key设置相应的属性
        switch (key) {
            case "1":
                break;
            case "2":
                Method userIdMethod = clazz.getMethod("getUserId");
                if (StrUtil.isEmpty((String) userIdMethod.invoke(objects))) {
                    throw new BusinessException("学工号不能为空");
                }
                break;
            case "3":
                Method user = clazz.getMethod("getUserId");
                Method getId = clazz.getMethod("getOrganizerId");
                if (StrUtil.isEmpty((String) user.invoke(objects)) && StrUtil.isEmpty((String) getId.invoke(objects))) {
                    throw new BusinessException("学工号或主办单位ID不能为空");
                }
        }

    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/623908.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

生产环境磁盘变更方案

datanode磁盘扩容(1人天) 扩容磁盘 1.1 扩容前检查、新盘初始化 确定block副本统计正常,无丢块,无under-replicated 块 后台执行命令检查 hdfs dfs fsck / 无异常可进行以下步骤进行磁盘扩容 新盘初始化 ##格式化新盘,命令示例: mkfs.xfs /dev/sdc##挂载新盘,命令示…

哔哩哔哩直播通用榜单系统

榜单系统的定位和业务价值 榜单遍布B站直播相关业务的各个角落&#xff0c;直播打赏、直播间互动、付费玩法、互动玩法、活动、主播PK、语聊房、人气主播排名、高价值用户排名、增值集卡、up主充电等等&#xff0c;在这众多的业务场景中&#xff0c;我们能看到各种各样的榜单。…

Allegro如何输出各层PCB视图的PDF文件

如何输出各层PCB视图的PDF文件 1、说明 用Allegro设计好PCB后&#xff0c;有时需要出各层的PDF文档出来进行汇报和展示&#xff0c;这时就需要将各层的平面视图全部以PDF的形式加载出来&#xff0c;具体方法如下。 2、PDF文件的输出方法&#xff08;以四层板为例&#xff09; …

网上跳蚤市场|基于SSM+vue的网上跳蚤市场系统的设计与实现(源码+数据库+文档)

网上跳蚤市场系统 目录 基于SSM&#xff0b;vue的网上跳蚤市场系统的设计与实现 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2后台登录模块 5.2.1管理员功能 5.2.2会员功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八…

如何内网穿透,远程访问内网设备

文章目录 0.前言1.准备工作2.内网穿透原理3.配置公网服务器的frp5.配置访问内网主机6.配置win10的远程桌面访问&#xff08;win11类似&#xff09;7.参考资料 0.前言 最近想研究一些新东西&#xff0c;公司的机器不敢乱搞&#xff0c;公司测试的服务器安装软件太多&#xff0c…

SQL Server服务启动缓慢或崩溃问题分析

关键词&#xff1a;SQL Server故障解决、服务启动缓慢、服务崩溃、日志文件清理 阅读建议&#xff1a;如果您遇到的是SQL Server服务启动缓慢或无法响应的问题&#xff0c;可以重点阅读文章的第一部分&#xff1b;如果是服务崩溃或重启的问题&#xff0c;可以重点关注第二部分。…

React 第三十章 React 和 Vue 描述页面的区别

面试题&#xff1a;React 和 Vue 是如何描述 UI 界面的&#xff1f;有一些什么样的区别&#xff1f; 标准且浅显的回答&#xff1a; React 中使用的是 JSX&#xff0c;Vue 中使用的是模板来描述界面 前端领域经过长期的发展&#xff0c;目前有两种主流的描述 UI 的方案&#xf…

如何在 Linux 上检查 CPU 和硬盘温度

为了更好地监测您的Linux系统的硬件健康状况&#xff0c;如CPU与硬盘温度、风扇转速等关键指标&#xff0c;采用lm_sensors与hddtemp这两款强大工具是明智之选。以下是关于这些工具的详尽指南&#xff0c;包括它们的功能介绍、安装步骤以及如何配置lm_sensors&#xff0c;旨在为…

C++的相关知识集

1、C概述 1 两大编程思想 c语言在c语言的基础上添加了面向对象编程和泛型编程的支持。c继承了c语言高效&#xff0c;简洁&#xff0c;快速和可移植的传统。 2 起源 与c语言一样&#xff0c;c也是在贝尔实验室诞生的&#xff0c;Bjarne Stroustrup(本贾尼斯特劳斯特卢普)在2…

自动化工具 Ansible:playbooks 剧本编写

目录 前言 一、playbooks 剧本概述 1、playbooks 剧本概念 2、playbooks 剧本组成部分 3、playbooks 剧本特点与优势 二、ansible-playbook 命令 三、playbooks 剧本简单实例 1、编写 apache 的 yum 安装部署脚本 2、编写 nginx 的 yum 安装部署剧本 四、playbooks 定…

【云原生】Kubeadm搭建K8S

一、部署Kubernetes 实验环境 服务器主机名IP地址主要组件k8s集群master01 etcd01master01192.168.10.100kube-apiserver kube-controller-manager kube-schedular etcdk8s集群node01 etcd02node01192.168.10.101kubelet kube-proxy docker flannelk8s集群node02 etcd03nod…

【源码+文档+调试讲解】微信小程序家政项目小程序

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序家政项目小程序的开发全过程。通过分析微信小程序家政项目小程序管理的不足&#xff0c;创建了一个计算机管理微信小程序家政项目小程序的方案。文章介…

Android 使用RecyclerView实现商品列表

实现步骤&#xff1a; 创建数据模型 创建一个表示商品的类&#xff0c;例如ProductInfo创建适配器 创建一个继承自RecyclerView.Adapter的适配器类&#xff0c;用于处理RecyclerView中的数据和视图在主页面布局文件中添加RecyclerView创建Item 布局文件在你的Activity或Fragme…

Vue3实战笔记(19)—封装菜单组件

文章目录 前言一、封装左侧菜单导航组件二、使用步骤三、小彩蛋总结 前言 在Vue 3中封装一个左侧导航菜单组件是一项提升项目结构清晰度和代码可复用性的关键任务。这个过程不仅涉及组件的设计与实现&#xff0c;还需考虑其灵活性、易用性以及与Vue 3新特性的紧密结合。以下是…

yarn 安装以及报错处理

前一种报错是由于没有安装yarn导致的&#xff0c;使用以下命令即可安装&#xff1a; npm install -g yarn 如果成功安装&#xff0c;将显示Yarn的版本号。 yarn --version 第二种报错是因为系统上的执行策略限制导致的。执行策略是一种安全功能&#xff0c;用于控制在计算机…

案例分享 I 千视协助Lentia City 购物中心实现轻量化、数字化转型

随着文娱活动的日益复苏&#xff0c;Lentia City作为奥地利最受欢迎的社交和文化聚集地之一&#xff0c;正逐渐成为人们追逐乐趣和交流的热门去处。这里丰富多彩的音乐表演和活动吸引着大量人群&#xff0c;为城市注入了生机和活力。 这些活动不仅仅是简单的娱乐&#xff0c;它…

IT行业的现状与未来发展趋势

目录 前言1. 当前IT行业的技术革新1.1 量子计算1.2 虚拟现实&#xff08;VR&#xff09;和增强现实&#xff08;AR&#xff09; 2. 新兴技术在不同行业中的应用前景2.1 云计算和大数据2.2 物联网&#xff08;IoT&#xff09;和5G通信2.3 区块链 3. 新兴技术对教育体系的挑战和机…

5分钟用 Python 写一个软件,快速入门 PySimpleGUI

大家好&#xff0c;很多人都想写一个自己的桌面程序&#xff0c;那么PySimpleGUI 是一个非常好的选择&#xff0c;它旨在简化 GUI&#xff08;图形用户界面&#xff09;的创建过程。它基于几种流行的 Python GUI 库&#xff0c;如 tkinter、Qt、WxPython 和 Remi&#xff0c;但…

Hive的join操作

假设有三张表&#xff0c;结构和数据如下&#xff1a;-- 创建表 test_a,test_b,test_c CREATE TABLE test_a( id int, name string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY \t;--分别导入数据到三个表中 --test_a 1 a1 2 a2 4 a4 --test_b 1 b1 3 b3 4 b4 --…

探索ISP静态:网络连接的稳定基石

在数字化时代的浪潮中&#xff0c;互联网已成为我们生活、工作、学习不可或缺的一部分。而网络连接的质量&#xff0c;直接决定了我们在线体验的好坏。在众多网络连接技术中&#xff0c;“ISP静态”作为一种稳定、可靠的网络连接方式&#xff0c;越来越受到广大用户的青睐。本文…