java接口加密解密

这里写目录标题

  • controller
  • 加解密工具类
  • 加密(本质是对@ResponseBody加密)
  • 解密(本质是对@RequestBody传参解密)
  • 注解

controller

@Controller
public class PathVariableController {

    @GetMapping(value = "/test")
    @ResponseBody
    public HashMap<String, Object> test() {
        HashMap<String, Object> map = new HashMap<>();
        map.put("data","successqqqqqq");
        map.put("code",200);
        map.put("msg","成功");
        return map ;
    }

    @PostMapping(value = "/us")
    @ResponseBody
    public HashMap<String, Object> us(@RequestBody User user) {
        System.out.println(user.getAge()+user.getName());
        HashMap<String, Object> map = new HashMap<>();
        map.put("data",user.getName());
        map.put("code",200);
        map.put("msg",user.getAge());

//        map.put("name","lidapao里大炮");
//        map.put("age",18);
        return map ;
    }
}

加解密工具类

package org.example.demo.demos.web;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.security.Key;
import java.util.Base64;

public class DESUtil {

    /**
     * 偏移变量,固定占8位字节
     */
    private final static String IV_PARAMETER = "12345678";
    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "DES";
    /**
     * 加密/解密算法-工作模式-填充模式
     */
    private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
    /**
     * 默认编码
     */
    private static final String CHARSET = "utf-8";

    /**
     * 生成key
     *
     * @param password
     * @return
     * @throws Exception
     */
    private static Key generateKey(String password) throws Exception {
        DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        return keyFactory.generateSecret(dks);
    }


    /**
     * DES加密字符串
     *
     * @param password 加密密码,长度不能够小于8位
     * @param data 待加密字符串
     * @return 加密后内容
     */
    public static String encrypt(String password, String data) {
        if (password== null || password.length() < 8) {
            throw new RuntimeException("加密失败,key不能小于8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(password);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));

            //JDK1.8及以上可直接使用Base64,JDK1.7及以下可以使用BASE64Encoder
            //Android平台可以使用android.util.Base64
            return new String(Base64.getEncoder().encode(bytes));

        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }

    /**
     * DES解密字符串
     *
     * @param password 解密密码,长度不能够小于8位
     * @param data 待解密字符串
     * @return 解密后内容
     */
    public static String decrypt(String password, String data) {
        if (password== null || password.length() < 8) {
            throw new RuntimeException("加密失败,key不能小于8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(password);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            return new String(cipher.doFinal(Base64.getDecoder().decode(data.getBytes(CHARSET))), CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }

    /**
     * DES加密文件
     *
     * @param srcFile  待加密的文件
     * @param destFile 加密后存放的文件路径
     * @return 加密后的文件路径
     */
    public static String encryptFile(String password, String srcFile, String destFile) {

        if (password== null || password.length() < 8) {
            throw new RuntimeException("加密失败,key不能小于8位");
        }
        try {
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, generateKey(password), iv);
            InputStream is = new FileInputStream(srcFile);
            OutputStream out = new FileOutputStream(destFile);
            CipherInputStream cis = new CipherInputStream(is, cipher);
            byte[] buffer = new byte[1024];
            int r;
            while ((r = cis.read(buffer)) > 0) {
                out.write(buffer, 0, r);
            }
            cis.close();
            is.close();
            out.close();
            return destFile;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * DES解密文件
     *
     * @param srcFile  已加密的文件
     * @param destFile 解密后存放的文件路径
     * @return 解密后的文件路径
     */
    public static String decryptFile(String password, String srcFile, String destFile) {
        if (password== null || password.length() < 8) {
            throw new RuntimeException("加密失败,key不能小于8位");
        }
        try {
            File file = new File(destFile);
            if (!file.exists()) {
                file.getParentFile().mkdirs();
                file.createNewFile();
            }
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, generateKey(password), iv);
            InputStream is = new FileInputStream(srcFile);
            OutputStream out = new FileOutputStream(destFile);
            CipherOutputStream cos = new CipherOutputStream(out, cipher);
            byte[] buffer = new byte[1024];
            int r;
            while ((r = is.read(buffer)) >= 0) {
                cos.write(buffer, 0, r);
            }
            cos.close();
            is.close();
            out.close();
            return destFile;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }


    public static void main(String[] args) {
        String key = "98fbffd1064a4355b8abaacb6fa96f94";
        String data="bDyb3N+87Imt+LmOEklv+ttCM2Z/5pHnYbJKbQ41bvozUKMMSrScP/xhHCYUJBrKI/aIDaDs7BE=";
    //String data="Khrcd+W7L/+PkWYPB/2qrgL7G8agzQXJ2xWdU8q67sfpjBd+C9nwEFdqDiBpbtTGP8jjcUJnOYILEMPtbKH+6YiqhMcluTRlkoXrPePhfQFOa/69mrwXn42jZsx1g1mR7AqOwdoGoz2rIQRh5RAn3uFuaN9nonQ2sFhxb9f+YA/5umlWVc8v37t4RmrFv4PO0xlqNV4lkXgdj2AnvUqxfBIizKXRgxFdvyqwydiXEL2+sMMc1B/mJY1C8N1pK92St/rF9Bj94fZdewHL3pQklxfl3c1bVqXexIY/CjCrSwmhkTdKMWWC4+81Z9kPlNUDnas3b2Wi/OgoHJVuQIhXShu+KSqBSxWPkECNo6OX/L5zUUa45NOIUOqXVduZhxlvm1/CvzgqLUPlEaAWfIZWzw==";
//        System.out.println("加密前key:" + key);
//        System.out.println("加密前data:" + key);
//        String rc="{\"corpKey\":\"913205080884374764\"}";
//        String en = encrypt(key,rc);
//        System.out.println("加密后:" + en);
        String de = decrypt(key,data);
        System.out.println("解密后:" + de);
    }
}

加密(本质是对@ResponseBody加密)

package com.ruoyi.framework.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.annotation.Encrypt;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DESUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;
import java.util.Map;

/**
 * 加解密接口处理
 */
@RestControllerAdvice
public class EncodeAdvice implements ResponseBodyAdvice {

    private Logger log = LoggerFactory.getLogger(EncodeAdvice.class);


    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Nullable
    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        boolean encode = true;
        // 出参 配置文件控制 默认打开
        String isEncrypt = RuoYiConfig.getIsEncrypt();
        if ("true".equals(isEncrypt)) {
            if (methodParameter.getMethod().isAnnotationPresent(Encrypt.class)) {
                Encrypt serializedField = methodParameter.getMethodAnnotation(Encrypt.class);
                encode = serializedField.encode();
            }
            if (encode) {
                log.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行加密");
                String secretPrivateKey = RuoYiConfig.getPrivateKey();
                ObjectMapper objectMapper = new ObjectMapper();
                try {
                    String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(body);
                    Map<String, String> data = new HashMap<>();
                    String enData = DESUtil.encrypt("98fbffd1064a4355b8abaacb6fa96f94", result);
                    // String enData2 = RsaUtils.encryptByPublicKey(RuoYiConfig.getPublicKey(), result);
                    data.put("data", enData);
                    // String s3 = RsaUtils.decrypt(RuoYiConfig.getPrivateKey(), enData);
                    return data;
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行加密出现异常:" + e.getMessage());
                }
            }
        }
        return body;
    }
}

解密(本质是对@RequestBody传参解密)

package com.ruoyi.framework.config;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Encrypt;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.DESUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.InputStream;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Map;

@Slf4j
@RestControllerAdvice
public class DecodeAdvice implements RequestBodyAdvice {


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

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,
                                           Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        try {
            // 入参默认加密
            boolean isDecode = true;
            if (parameter.getMethod().isAnnotationPresent(Encrypt.class)) {
                Encrypt encrypt = parameter.getMethodAnnotation(Encrypt.class);
                isDecode = encrypt.decode();
            }
            if (isDecode) {
                log.info("对方法method :【" + parameter.getMethod().getName() + "】入参进行解密");
                if (inputMessage.getHeaders().containsKey("requestType")) {
                    String requestType = inputMessage.getHeaders().get("requestType").get(0);
                    if (requestType.equals("post")) {
                        return new MyHttpInputMessage(inputMessage, requestType);
                    } else if (requestType.equals("put")) {
                        return new MyHttpInputMessage(inputMessage, requestType);
                        // return inputMessage;
                    } else {
                        return inputMessage;
                    }
                } else {
                    return inputMessage;
                }
            } else {
                return inputMessage;
            }
        } catch (Exception e) {
            log.error("对方法method :【" + parameter.getMethod().getName() + "】入参解密失败");
            log.error(ExceptionUtil.getMessage(e));
            return inputMessage;
        }
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
                                Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    @Override
    public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter,
                                  Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return body;
    }

    class MyHttpInputMessage implements HttpInputMessage {
        private HttpHeaders headers;

        private InputStream body;

        /**
         * inputMessage 解密后重新赋值
         *
         * @param inputMessage
         * @param requestType
         * @throws Exception
         */
        public MyHttpInputMessage(HttpInputMessage inputMessage, String requestType) throws Exception {
            this.headers = inputMessage.getHeaders();
            if (requestType.equals("put")) {
                InputStream inputStream = inputMessage.getBody();
                String body = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);
                this.body = IOUtils.toInputStream(easpString(body), "utf-8");
            } else {
                this.body = IOUtils.toInputStream(easpString(IOUtils.toString(inputMessage.getBody(), "utf-8")), "utf-8");
            }
        }

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

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

        /**
         * @param requestData
         * @return
         */
        public String easpString(String requestData) {
            if (requestData != null && !"".equals(requestData)) {
                Map<String, String> map = JSONObject.parseObject(requestData, Map.class);
                // 密文
                String isEncrypt = RuoYiConfig.getIsEncrypt();
                if (isEncrypt.equals("false")) {
                    return requestData;
                }
                String data = map.get("dataBody");
                if (StringUtils.isEmpty(data)) {
                    throw new RuntimeException("参数【requestData】缺失异常!");
                } else {
                    String content;
                    try {
                        content = DESUtil.decrypt("98fbffd1064a4355b8abaacb6fa96f94", data);
                    } catch (Exception e) {
                        throw new RuntimeException("参数解析异常!");
                    }
                    return content;
                }
            }
            throw new RuntimeException("参数【requestData】不合法异常!");
        }
    }
}

注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Encrypt {


    /**
     * 接收参数是否解密 默认true
     * @param
     */
    boolean decode() default true;

    /**
     * 返回体是否加密 默认true
     * @return
     */
    boolean encode() default true;

}

在这里插入图片描述

== 加解密的配置从yaml配置文件里读 ==

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

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

相关文章

【Mysql】mysql本地环境变量的配置

mysql本地环境变量的配置 1.找到Mysql的安装位置 前面步骤完成后安装好MySQL&#xff0c;为MySQL配置环境变量。MySQL默认安装在C:\Program Files下。 2.选择此电脑 右键属性 3.选择 高级系统设置 环境变量 4.配置环境变量 1)新建MYSQL_HOME变量,并配置: C:\Program Fi…

李沐-28 批量归一化【动手学深度学习v2】

记录关于批量归一化的理解&#xff0c;如有出入还请批评指正。 一、批量归一化层主要作用在以下两种情况&#xff1a; 全连接层和卷积层的输出上&#xff0c;同时要在激活函数之前还可以是全连接层和卷积层的输入上 二、关于“批量归一化对于全连接层时&#xff0c;是作用在特…

vue 实现项目进度甘特图

项目需求&#xff1a; 实现以1天、7天、30天为周期&#xff08;周期根据筛选条件选择&#xff09;&#xff0c;展示每个项目不同里程碑任务进度。 项目在Vue-Gantt-chart: 使用Vue做数据控制的Gantt图表基础上进行了改造。 有需要的小伙伴也可以直接引入插件&#xff0c;自己…

基于springboot实现企业级工位管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现企业级工位管理系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了企业级工位管理系统的开发全过程。通过分析企业级工位管理系统管理的不足&#xff0c;创建了一个计算机管理企业级工…

【深度学习】YOLOv5,金属表面的缺陷检测,GC10-DET数据集

目录&#xff1a; 文章目录 数据集数据集转换下载yolov5创建 dataset.yaml训练参数开始训练数据分布问询、帮助 数据集 数据集地址&#xff1a; https://github.com/lvxiaoming2019/GC10-DET-Metallic-Surface-Defect-Datasets 数据集下载方式&#xff1a; Download link&…

transformer 最简单学习3, 训练文本数据输入的形式

1、输入数据中&#xff0c;源数据和目标数据的定义 def get_batch(source,i):用于获取每个批数据合理大小的源数据和目标数据参数source 是通过batchfy 得到的划分batch个 ,的所有数据&#xff0c;并且转置列表示i第几个batchbptt 15 #超参数&#xff0c;一次输入多少个ba…

Spring事务回滚核心源码解读

记一次Springboot事务超时不回滚的分析过程 在Springboot中&#xff0c;我用的xml进行事务管理&#xff0c;DataSourceTransactionManager作为事务管理器&#xff0c;配置了事务控制在Service层&#xff1b;在事务管理器中&#xff0c;配置了defaultTimeout事务超时时间为5秒&…

云香印象终端自动化工具(监听农行收款云音箱)

项目成品 支持自动挂单✅完成监控收款云音箱✅完成卷烟盘点✅完成补单✅完成自动入库✅完成监控微信支付✅完成自动提交会员信息✅完成 用到的技术栈&#xff1a;PythonMQTT5.0PHP 云香印象终端自动收款工具 ​​​​​ 当顾客扫了三合一二维码且支付完成时&#xff0c;监控收到…

精酿啤酒:酿造工艺的自动化与智能化发展

随着科技的不断进步&#xff0c;自动化与智能化已成为啤酒酿造工艺的重要发展方向。Fendi Club啤酒紧跟时代潮流&#xff0c;积极推动酿造工艺的自动化与智能化发展&#xff0c;旨在提高生产效率、确保产品品质和满足市场需求。 Fendi Club啤酒引入自动化生产设备。他们采用自动…

Mybatis-plus 字段结果为NULL

问题 Mybatis-plus 字段结果为NULL 详细问题 笔者使用SpringBootMybatis-plus 进行项目开发。进行接口请求测试&#xff0c;在确定SQL语句没有问题的前提下&#xff0c;返回记录部分字段(譬如字段name)为空。 解决方案 修改Mybatis-plus中mapper的xml文件&#xff0c;使re…

CentOS7版本安装mysql

文章目录 1.安装mysql的前置条件2.清理原有的mysql数据库3.查看是否安装mariadb4.安装mysql依赖包5.解压缩mysql包6.安装目录赋权限&#xff08;注&#xff1a;R必须是大写&#xff09;7.创建MySQL组8.将mysql目录的权限授给mysql用户和mysql组9.创建mysql安装初始化配置文件10…

APP广告变现项目

我们提供的服务可以简化为以下几点&#xff1a; 我们将为您开发一款应用程序(APP)&#xff0c;该APP能够连接市场上的主要广告联盟平台。 我们将指导您完成整个“养机”流程&#xff0c;并确保您的单台设备每条广告能产生大约1元的收益。若您拥有10台设备&#xff0c;每日收益…

ElasticSearch搜索引擎中,在Kibana客户端使用命令的时候,千万不要加分号结尾

ElasticSearch搜索引擎中&#xff0c;在Kibana客户端使用命令的时候&#xff0c;千万不要加分号结尾 今天遇到了一个非常难发现的bug 由于经常写java代码&#xff0c;因此常常会在一句代码结尾之处写上一个分号&#xff0c;并且潜意识里觉得这就是非常正常的事情 不会有什么问…

c++的智能指针(5) -- weak_ptr

概述 我们在使用shared_ptr会出现以下的问题&#xff0c;会导致内存泄露。 代码1: 类内指针循环指向 #include <iostream> #include <memory>class B;class A { public:A() {std::cout << "Construct" << std::endl;}~A() {std::cout <…

鸿蒙入门11-DataPanel组件

数据面板组件 用于将多个数据的占比情况使用 占比图 进行展示 参数 参数形式 &#xff1a; DataPanel( options:{ values: number[], max?: number, type?: DataPanelType } ) 参数名 参数类型 是否必填 默认值 参数描述 values number[] 是 - 数据值列表 最大支持…

Android Studio的button点击事件

xml添加onClick调用方法 public class MainActivity extends AppCompatActivity {// 创建系统时间的文本控件TextView systemTimeTextView;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activit…

Springboot+Vue项目-基于Java+MySQL的海滨体育馆管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Jmeter工具+ant+jenkins实现持续集成

jmeterantjenkins持续集成 一、下载并配置jmeter 首先下载jmeter工具&#xff0c;并配置好环境变量&#xff1b;参考&#xff1a; jmeter默认保存的是.jtl格式的文件&#xff0c;要设置一下bin/jmeter.properties,文件内容&#xff0c;保存jmeter.save.saveservice.output_f…

【linux】Bad owner or permissions on

在root用户下执行scp操作向另外一个节点拷贝文件时发生了如下错误&#xff1a; Bad owner or permissions on /etc/crypto-policies/back-ends/openssh.config 我们查看他的权限时发现它所链接的文件权限为777 解决方法就是&#xff1a; chmod 600 /etc/crypto-policies/back-e…

关于加强电力系统通信与电网调度自动化建设问题的规定

关于加强电力系统通信与电网调度自动化建设问题的规定 为了保障电力系统安全、经济、优质、可靠运行&#xff0c;必须加强电网调度管理和提高技术装备水平。根据当前电网技术装备状况&#xff0c;结合电力系统通信和电网调度自动化的特点&#xff0c;以及今后规划发展的要求&am…