AES实现接口的安全性

news2025/7/20 21:13:35

文章目录

  • Maven项目结构图
  • 引入依赖
  • AESUtils
  • EnDecryptUtil
  • EncryptProperties
  • EncryptAutoConfiguration
  • spring.factories
  • 打成jar包,供其他项目 / 人使用
    • 打成jar 包
    • 导入 jar 包
  • 测试
    • application.yaml
    • User类
    • HelloController 测试

代码地址:
链接:https://pan.baidu.com/s/1SKKo6yMG6gQOe6G2TCuAqw
提取码:yyds

Maven项目结构图

在这里插入图片描述

引入依赖


<!-- jar 包的名称 artifactId-->
<groupId>com.github.encrypt</groupId>
<artifactId>encrypt-spring-boot-starter</artifactId>
<version>1.0</version>

<properties>
    <java.version>1.8</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

</dependencies>

AESUtils


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

public class AESUtils {

    private static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";

    // 获取 cipher
    private static Cipher getCipher(byte[] key, int model) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec (key, "AES");
        Cipher cipher = Cipher.getInstance (AES_ALGORITHM);
        cipher.init (model, secretKeySpec);
        return cipher;
    }

    // AES 加密
    public static String encrypt(byte[] data, byte[] key) throws Exception {
        Cipher cipher = getCipher (key, Cipher.ENCRYPT_MODE);
        return java.util.Base64.getEncoder ().encodeToString (cipher.doFinal (data));
    }

    // AES 解密
    public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
        Cipher cipher = getCipher (key, Cipher.DECRYPT_MODE);
        return cipher.doFinal (Base64.getDecoder ().decode (data));
    }
}

EnDecryptUtil

http 传输会把 + 号转为 空格
把 所有空格换成 +号,这是个 bug

package endecode;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;


@NoArgsConstructor
@Slf4j
public class EnDecryptUtil {

    private String key;
    private ObjectMapper om;

    public EnDecryptUtil(String key, ObjectMapper om) {
        this.om = om;
        this.key = key;
    }

    public <T> T decrypt(String data, Class<T> classType) throws Exception {

        log.info ("decrypt  method start ");
        if (key == null || key.length () != 16) {
            log.error ("spring.encrypt.key 不能为空 或长度不满足16!");
            return classType.newInstance ();
        }
        byte[] keyBytes = key.getBytes ();

        if (data == null || data.length () == 0) {
            log.error ("解密的数据 不能为空!");
            return classType.newInstance ();
        }
        char[] dataChars = data.toCharArray ();
        // http 传输会把 +号转为 空格
        //把 所有空格换成 +号,这是个bug
        boolean flag = false;
        for (int i = 0; i < dataChars.length; i++) {
            if (dataChars[i] == ' ') {
                dataChars[i] = '+';
                flag = true;
            }
        }
        if (flag) data = new String (dataChars);

        byte[] dataBytes = data.getBytes ();
        log.info ("请求(原加密)参数:{}", data);

        byte[] decrypt = new byte[0];

        try {
            decrypt = AESUtils.decrypt (dataBytes, keyBytes);
        } catch (Exception e) {

            log.error (" 请求参数(原加密)错误 / key 错误,无法解析", e.getMessage ());
            return classType.newInstance ();
        }

        if (decrypt.length == 0) return null;
        T rawData = null;

        try {
            rawData = om.readValue (decrypt, classType);
        } catch (IOException e) {
            log.error ("readValue转化 Exception,parameters:{}", rawData);
            e.printStackTrace ();
        }
        log.info ("解密后的参数: {}", rawData);

        log.info ("decrypt  method  end ");
        return rawData == null ? classType.newInstance () : rawData;
    }

    public <T> String encrypt(T data) {
        if (data == null) {
            log.error ("加密的数据 不能为空!");
            return "加密的数据 不能为空!";
        }
        log.info ("encrypt  method start ");
        if (key == null || key.length () != 16) {
            log.error ("spring.encrypt.key 不能为空 或长度不满足16!");
            return "spring.encrypt.key 不能为空 或长度不满足16!";
        }
        byte[] keyBytes = key.getBytes ();
        String encryptData = null;
        try {
            encryptData = AESUtils.encrypt (om.writeValueAsBytes (data), keyBytes);
        } catch (Exception e) {
            log.error ("  加密失败 / key 错误,无法解析", e.getMessage ());
        }

        log.info ("encrypt  method  end ");
        return encryptData == null ? "加密失败" : encryptData;
    }


}

EncryptProperties

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "spring.encrypt")
public class EncryptProperties {
    private final static String DEFAULT_KEY = "1Pxwol9WnHtpD5Tz";
    private String key = DEFAULT_KEY;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }
}

EncryptAutoConfiguration

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

@Configuration
@ComponentScan("endecode")
public class EncryptAutoConfiguration {

    @Resource
    private EncryptProperties encryptProperties;
    @Resource
    private ObjectMapper om;

    @Bean("enDecryptUtil")
    public EnDecryptUtil enDecryptUtil() {

        return new EnDecryptUtil (encryptProperties.getKey (), om);
    }
}

spring.factories

resources下新建目录META-INF

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  endecode.EncryptAutoConfiguration

打成jar包,供其他项目 / 人使用

打成jar 包

在这里插入图片描述

在这里插入图片描述

起个名
在这里插入图片描述

选择要导出的模块
在这里插入图片描述
在这里插入图片描述
**左上角 工具栏处 **
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看jar包 所在目录
在这里插入图片描述
在这里插入图片描述

导入 jar 包

在这里插入图片描述
在这里插入图片描述

测试

application.yaml

spring:
  encrypt:
    key: woshigedashuaige

User类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String username;
    //省略 getter/setter
}

HelloController 测试

import com.example.demo.util.Result;
import endecode.EnDecryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;


@RestController
@Slf4j
public class HelloController {

    @Resource
    //引入enDecryptUtil
    private EnDecryptUtil enDecryptUtil;

    @GetMapping("/user")

    public Result getUser() {
        User user = new User (100L, "I am xiao ding");
        //加密
        String encryptData = enDecryptUtil.encrypt (user);
        return Result.ok (encryptData);

    }

    @PostMapping("/user")
    // http传输会把 +号转为空格
    public Result addUser(String encodeMsg) throws Exception {
        //解密
        User user = enDecryptUtil.decrypt (encodeMsg, User.class);
        if (user.getId () == null) {
            user.setId (1L);
            user.setUsername ("找不到");
        }
        return Result.ok (user);
    }
}

启动项目

加密操作

在这里插入图片描述

返回的是加密后的数据

在这里插入图片描述

解密操作

参数为空 或者不正确
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

参数正确

在这里插入图片描述
在这里插入图片描述

完成

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入理解java虚拟机:类文件结构(1)

文章目录1. 概述2. Class类文件的结构2.1 魔数与Class文件的版本2.2 常量池2.3 访问标志2.4 类索引、父类索引与接口索引集合2.5 字段表集合1. 概述 如果计算机的CPU指令集就只有x86一种&#xff0c;操作系统就只有Windows一种&#xff0c;那也许就不会有Java语言的出现。Java…

云原生:容器与微服务

目录 一、虚拟化与容器 1.1 虚拟机 1.2 容器 1.3 Docker 1.4 Docker代码示例 二、微服务 2.1 微服务的概念 2.2 微服务的特点 三、为什么使用微服务 3.1 微服务的优缺点 3.2 云原生的支持服务 云原生技术使组织能够在新式动态环境&#xff08;如公有云、私有云和混…

攻防世界-pwnCTFM-Off_By_one漏洞与Tcachebin绕过

攻防世界-pwnCTFM-Off_By_one漏洞与Tcachebin绕过 保护机制 healerhealer-virtual-machine:~/Desktop/pwnCTFM/attachments$ checksec pwn [*] /home/healer/Desktop/pwnCTFM/attachments/pwnArch: amd64-64-littleRELRO: Full RELROStack: Canary foundNX: …

线性判别分析(机器学习)

目录 线性判别分析的原理 LDA的降维过程如下 线性判别分析&#xff08;LDA&#xff09; 是一种有监督的线性降维算法。 与PCA不同&#xff0c;LDA是为了使降维后的数据点尽可能地容易被区分 线性判别分析的原理 线性判别分析是对于给定的训练集&#xff0c;设法将样本投影到…

基于HTML+CSS+JavaScript+Bootstarp响应式健身网站(web前端期末大作业)

网站题目> &#x1f3c0;校园篮球网页设计、⚽足球体育运动、&#x1f93d;体育游泳运动、&#x1f3d3;兵乓球 、&#x1f3be;网球、等网站的设计与制作。 二、✍️网站描述> &#x1f3f7;️ 大学生校园运动静态HTML网页设计作品&#xff0c;采用DIV CSS布局制作&am…

数据结构体进阶链表【带头双向循环链表,单向链表的优化,从根部解决了顺序表的缺点】一文带你深入理解链表

前言&#xff1a; 对于链表&#xff0c;上一篇的单链表解决了顺序表的一部分缺陷&#xff0c;但并没有彻底的解决顺序表的问题&#xff0c;比如在进行单链表尾插尾删的时候还是需要进行遍历找尾&#xff0c;并没有达到全部的O(1)&#xff0c;并且在头插的时候还要分情况来考虑&…

【ASM】字节码操作 工具类与常用类 AdviceAdapter 介绍 打印方法进入 和 方法退出 的参数

文章目录 1.概述2. AdviceAdapter类2.1 class info2.2 fields2.3 constructors2. 4 methods2.案例2.1 打印方法参数3.总结1.概述 在上一篇文章:【ASM】字节码操作 工具类与常用类 Printer、ASMifier、Textifier 介绍 我们简单的介绍了 Printer、ASMifier、Textifier 三个类的…

idea2021版本创建一个javaweb项目(含额外知识--添加tomcat相关jar包)

前言&#xff1a; 建立一个javaweb项目需要用到JDK、idea、Tomcat 1. JDK是11版本的 2.IDEA是2021版本的 3.Tomcat是8.5版本的 这些下载在我的其他文章里面也有讲到下载和应用&#xff0c;大致都是殊途同归的 一、打开ided&#xff0c;按照以下步骤点击创建一个工程项目…

X11 Xlib截屏代码所遇问题及初步分析

综合了两篇博客中的例程并做一定修改&#xff0c;得到了基于X11 Xlib的截屏代码。 两篇博客链接分别如下&#xff1a; X11 截图与鼠标事件-SkyMei777-ChinaUnix博客 xlib实现截图报错-编程语言-CSDN问答 C代码如下&#xff1a; #include <stdio.h> #include <std…

[附源码]SSM计算机毕业设计自治小区物业设备维护管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

TK选品技巧 | 听说TikTok畅销品都是这样来的

9月16日消息&#xff0c;TikTok Shop发布东南亚99大促战报&#xff0c;此次战报数据包含了马来西亚、新加坡、菲律宾、越南和泰国五国销售数据&#xff0c;战报显示&#xff0c;此次东南亚99大促总GMV增幅达156%&#xff0c;总live GPM增幅达130%&#xff0c;订单量增幅达128%&…

基于springboot的社区疫情管理系统源码

1、项目介绍 基于springboot的社区疫情管理系统拥有三种角色&#xff1a;超级管理员、普通管理员、用户 超级管理员&#xff1a;管理员和用户管理、人员检测信息管理、外来人员报备管理、防疫须知管理、疫情用品类型管理、疫情用品管理、订单管理、评论管理、审核外来人员、新…

【ML-SVM案例学习】案例一:对鸢尾花数据进行SVM分类(附源码)

文章目录前言一、完整源码分步实现1.引入库2.读入数据3.编码数据4.数据分割5.数据SVM分类器构建6.计算模型的准确率/精度7.计算决策函数的结构值以及预测值8.画图总结前言 【ML-SVM案例学习】会有十种SVM案例&#xff0c;供大家用来学习。本章实现SVM鸢尾花数据的分类任务。 一…

PDF能编辑修改吗?教你必备的几种编辑方法

可以把PDF文件编辑修改吗&#xff1f;相信这是很多萌新在刚接触PDF文件时所产生的疑惑&#xff0c;因为在想要改动PDF文件的时候&#xff0c;发现无法直接编辑内容&#xff0c;就会有PDF文件可以编辑吗的疑问了&#xff0c;其实有这种想法非常正常&#xff0c;大家都是经历过的…

【设计模式】单例模式

单例模式属于创建型模式&#xff0c;是最简单的一种设计模式。当一个类在程序中只需要创建唯一全局对象时&#xff08;如网站计数类、日志管理类、线程池类……&#xff09;&#xff0c;就可以使用单例模式。单例模式规定一个类只能创建一个实例&#xff0c;之后不能再创建新的…

Verilog语法

Verilog语法 Verilog简介 Verilog是一种硬件描述语言&#xff0c;以文本形式来描述数字系统硬件的结构和行为的语言&#xff0c;用它可以表示逻辑电路图、逻辑表达式&#xff0c;还可以表示数字逻辑系统所完成的逻辑功能。 Verilog 和 C 的区别&#xff1a; Verilog是硬件描…

Linux篇【5】:Linux 进程概念(二)

目录 3.5、查看进程 3.6、通过系统调用接口获取时实进程的标识符 3.7、通过系统调用接口创建子进程 - fork 初识 3.5、查看进程 [HJMhjmlcc ~]$ clear [HJMhjmlcc ~]$ pwd /home/HJM [HJMhjmlcc ~]$ ls [HJMhjmlcc ~]$ touch mytest.c [HJMhjmlcc ~]$ ls mytest.c [HJMhjml…

G1D16-fraud-SVM

早上复习了一下昨天学的内容&#xff0c;发现这零碎时间用来复习&#xff0c;真的很不错。 但是遇到了一个问题&#xff1a;知识推理和知识挖掘有什么区别&#xff1f; 知识规则挖掘是对知识结构的挖掘&#xff0c;可以针对现有的知识体系&#xff0c; 利用部分规则&#xff0…

[附源码]java毕业设计冷链物流管理系统论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Redis数据类型之hash

文章目录hashⅠ. 增删查改Ⅱ. 加法操作Ⅲ. 业务场景1 - 购物车Ⅳ. 业务场景2 - 秒杀Ⅴ. 注意事项提示&#xff1a;以下是本篇文章正文内容&#xff0c;Redis系列学习将会持续更新 hash ● 新的存储需求&#xff1a;对一系列存储的数据进行编组&#xff0c;方便管理&#xff0c;…