java接口加密解密

news2025/1/18 11:40:25

这里写目录标题

  • 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.coloradmin.cn/o/1628069.html

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

相关文章

Redis缓存问题:穿透,击穿,雪崩等

Redis缓存问题:穿透,击穿,雪崩等 在高并发场景下,数据库往往是最薄弱的环节,我们通常选择使用redis来进行缓存,以起到缓冲作用,来降低数据库的压力,但是一旦缓存出现问题,也会导致数据库瞬间压力过大甚至崩溃,从而导致整个系统崩溃.今天就聊聊常见的redis缓存问题. 缓存击穿 …

相关分析方法

目录 1.什么是相关分析方法 2.相关系数 3.常见的相关分析方法 3.1.皮尔逊相关系数 3.2.斯皮尔曼等级相关 ​​​​​​​3.3.肯德尔等级相关 ​​​​​​​3.4.其它 4.应用 5.注意事项 6.结语 1.什么是相关分析方法 相关分析是数据分析中的一种统计方法&#xff0c…

[C++基础学习]----02-C++运算符详解

前言 C中的运算符用于执行各种数学或逻辑运算。下面是一些常见的C运算符及其详细说明&#xff1a;下面详细解释一些常见的C运算符类型&#xff0c;包括其原理和使用方法。 正文 01-运算符简介 算术运算符&#xff1a; a、加法运算符&#xff08;&#xff09;&#xff1a;对两个…

RabbitMQ(高级)笔记

一、生产者可靠性 &#xff08;1&#xff09;生产者重连&#xff08;不建议使用&#xff09; logging:pattern:dateformat: MM-dd HH:mm:ss:SSSspring:rabbitmq:virtual-host: /hamllport: 5672host: 192.168.92.136username: hmallpassword: 123listener:simple:prefetch: 1c…

AWTK 开源串口屏开发(17) - 通过 MODBUS 访问数组数据

在 AWTK 串口屏中&#xff0c;内置了 MODBUS Client Channel 的模型&#xff0c;不用编写代码即可实现在 ListView 中显示数组数据。 MODBUS 协议一次只能读取 125 个 WORD&#xff0c;AWTK-MODBUS Client Channel 支持长数据&#xff0c;自动分成多个请求访问。 1. 功能 不用…

浏览器的同源策略与解决跨域

同源策略&#xff08;协议、域名、端口&#xff09; 同源策略&#xff08;Same-Origin Policy&#xff09;是一个在浏览器安全模型中被实施的重要安全机制。它是基于域名、协议和端口号的限制&#xff0c;用于防止不同源的网页间的恶意行为和信息泄露。 根据同源策略&#xf…

【Diffusion实战】训练一个diffusion模型生成蝴蝶图像(Pytorch代码详解)

上一篇Diffusion实战是确确实实一步一步走的公式&#xff0c;这回采用一个更方便的库&#xff1a;diffusers&#xff0c;来实现Diffusion模型训练。 Diffusion实战篇&#xff1a;   【Diffusion实战】训练一个diffusion模型生成S曲线&#xff08;Pytorch代码详解&#xff09;…

【Linux学习】​​学习Linux的准备工作和Linux的基本指令

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

并并并并·病查坤

P1、什么是并查集 引用自百度百科&#xff1a; 并查集&#xff0c;在一些有N个元素的集合应用问题中&#xff0c;我们通常是在开始时让每个元素构成一个单元素的集合&#xff0c;然后按一定顺序将属于同一组的元素所在的集合合并&#xff0c;其间要反复查找一个元素在哪个集合…

【数据标注】使用LabelImg标注YOLO格式的数据(案例演示)

文章目录 LabelImg介绍LabelImg安装LabelImg界面标注常用的快捷键标注前的一些设置案例演示检查YOLO标签中的标注信息是否正确参考文章 LabelImg介绍 LabelImg是目标检测数据标注工具&#xff0c;可以标注两种格式&#xff1a; VOC标签格式&#xff0c;标注的标签存储在xml文…

insightface 环境配置

首先创建续集环境&#xff1a; conda create -n insightface3 python3.8 然后打开此虚拟环境&#xff1a;conda activate insightface3 然后安装&#xff1a; pip install insightface 再安装&#xff1a;pip install onnxruntime-gpu 就可以了

零基础俄语培训哪家好,柯桥俄语培训

1、Мощный дух спасает расслабленное тело. 强大的精神可以拯救孱弱的肉体。 2、Единственное правило в жизни, по которому нужно жить — оставаться человеком в лю…

物联网的基本功能及五大核心技术——青创智通

工业物联网解决方案-工业IOT-青创智通 物联网基本功能 物联网的最基本功能特征是提供“无处不在的连接和在线服务”&#xff0c;其具备十大基本功能。 &#xff08;1&#xff09;在线监测&#xff1a;这是物联网最基本的功能&#xff0c;物联网业务一般以集中监测为主、控制为…

qml和c++结合使用

目录 文章简介1. 创建qml工程2. 创建一个类和qml文件&#xff0c;修改main函数3. 函数说明&#xff1a;4. qml 文件间的调用5. 界面布局6. 代码举例 文章简介 初学qml用来记录qml的学习过程&#xff0c;方便后面归纳总结整理。 1. 创建qml工程 如下图&#xff0c;我使用的是…

本地Mysql开启远程访问(图文)

目录 1. 问题所示2. 原理分析3. 解决方法 1. 问题所示 事因是访问同事的数据库时&#xff0c;出现无法访问 出现1130 - Host ‘IT07’ is not allowed to connect to this MySQL server截图如下&#xff1a; 2. 原理分析 如果账号密码地址都正常的情况下&#xff0c;这是没开…

SQLite尽如此轻量

众所周知&#xff0c;SQLite是个轻量级数据库&#xff0c;适用于中小型服务应用等&#xff0c;在我真正使用的时候才发现&#xff0c;它虽然轻量&#xff0c;但不知道它却如此轻量。 下载 官网&#xff1a; SQLite Download Page 安装 1、将下载好的两个压缩包同时解压到一个…

基于springboot的高校宣讲会管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

前端工程化Vue使用Node.js永久设置国内高速npm镜像源

前端工程化Vue使用Node.js永久设置国内高速npm镜像源 接续上篇错误收录&#xff0c;此篇通过简单配置永久设置国内高速npm镜像源方法 1.更换新版镜像 清空npm缓存 npm cache clean --force修改回原版镜像源或直接删除配置过的镜像源 npm config set registry https://registr…

pve(Proxmox VE)安装i225v网卡驱动

配置pve源 备份原来的源 mv /etc/apt/sources.list /etc/apt/sources.list.bak打开文件 vi /etc/apt/sources.list将以下内容粘贴进去 deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmwaredeb https://mirrors.tuna.tsing…