当前位置: 首页 > 知识库问答 >
问题:

Spring Boot-加密JSON数据

苏运良
2023-03-14

在我们的应用程序中,我们必须为每个请求和响应加密/解密Json属性值(而不是属性名)。例如,
{“用户名”:“加密值”,“电子邮件”:“加密值”}

我们使用Sprint boot 1.3,使用@RequestBody和@ResponseBody注释将请求json与对象绑定,并将响应对象序列化为json。

我们不希望在每个控制器方法中调用加密/解密方法。在与请求对象绑定之前,我们是否可以指示sprint解密json值?类似地,要在将响应对象字段值转换为json之前对其进行加密吗?还是定制Jackson可以帮助我们?

谢谢!

共有2个答案

葛和志
2023-03-14

好的,所以我使用@eparvan的答案并做了一些修改。

  1. 创建一个加密JSON响应并从前端解密请求参数的组件

我在“data”对象中以加密格式获取请求参数,类似这样,并以与data对象相同的方式发送加密响应。

参考响应:{“数据”:“RequestorResponseInCryptedPrivateKey”}

    @Component
    public class Converter extends AbstractHttpMessageConverter<Object> {

        private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

        @Autowired
        private ObjectMapper objectMapper;

        public Converter() {
            super(MediaType.APPLICATION_JSON,
                    new MediaType("application", "*+json", DEFAULT_CHARSET));
        }

        @Override
        protected boolean supports(Class<?> clazz) {
            return true;
        }

        @Override
        protected Object readInternal(Class<? extends Object> clazz,
                                      HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
            return objectMapper.readValue(decrypt(inputMessage.getBody()), clazz);
        }

        @Override
        protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
            outputMessage.getBody().write(encrypt(objectMapper.writeValueAsBytes(o)));
        }

        /**
         * requests params of any API
         *
         * @param inputStream inputStream
         * @return inputStream
         */
        private InputStream decrypt(InputStream inputStream) {
            //this is API request params
            StringBuilder requestParamString = new StringBuilder();
            try (Reader reader = new BufferedReader(new InputStreamReader
                    (inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) {
                int c;
                while ((c = reader.read()) != -1) {
                    requestParamString.append((char) c);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                //replacing /n if available in request param json string

                //reference request: {"data":"thisisencryptedstringwithexpirytime"}

                JSONObject requestJsonObject = new
                        JSONObject(requestParamString.toString().replace("\n", ""));

                String decryptRequestString = EncryptDecrypt.decrypt(requestJsonObject.getString("data"));
                System.out.println("decryptRequestString: " + decryptRequestString);

                if (decryptRequestString != null) {
return new ByteArrayInputStream(decryptRequestString.getBytes(StandardCharsets.UTF_8));
                } else {
                    return inputStream;
                }
            } catch (JSONException err) {
                Log.d("Error", err.toString());
                return inputStream;
            }
        }

        /**
         * response of API
         *
         * @param bytesToEncrypt byte array of response
         * @return byte array of response
         */
        private byte[] encrypt(byte[] bytesToEncrypt) {
            // do your encryption here
            String apiJsonResponse = new String(bytesToEncrypt);

            String encryptedString = EncryptDecrypt.encrypt(apiJsonResponse);
            if (encryptedString != null) {
                //sending encoded json response in data object as follows

                //reference response: {"data":"thisisencryptedstringresponse"}

                Map<String, String> hashMap = new HashMap<>();
                hashMap.put("data", encryptedString);
                JSONObject jsob = new JSONObject(hashMap);
                return jsob.toString().getBytes();
            } else
                return bytesToEncrypt;
        }
    }

这是我的加密解密类,加密和解密正在进行

class EncryptDecrypt {

    static String encrypt(String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(Constants.Encryption.INIT_VECTOR.getBytes(StandardCharsets.UTF_8));
            SecretKeySpec skeySpec = new
                    SecretKeySpec("PRIVATE_KEY_FOR_ENCRYPTION_OR_DECRYPTION"
                    .getBytes(StandardCharsets.UTF_8), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

            byte[] encrypted = cipher.doFinal(value.getBytes());
            byte[] original = Base64.getEncoder().encode(encrypted);
            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    static String decrypt(String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(Constants.Encryption.INIT_VECTOR
                    .getBytes(StandardCharsets.UTF_8));
            SecretKeySpec skeySpec = new SecretKeySpec("PRIVATE_KEY_FOR_ENCRYPTION_OR_DECRYPTION".
                    getBytes(StandardCharsets.UTF_8), "AES");

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] original = cipher.doFinal(Base64.getDecoder().decode(encrypted));
            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

}

你完了!

孔冥夜
2023-03-14

您可以编写自己的http消息转换器。因为您使用的是spring boot,所以它非常简单:只需从AbstractHttpMessageConverter扩展您的自定义转换器,并用@Component注释标记该类。

从spring文档:

您可以通过在Spring Boot上下文中简单地添加该类型的bean来贡献额外的转换器。如果您添加的bean属于默认情况下应该包含的类型(如用于JSON转换的MappingJackson2HttpMessageConverter),那么它将替换默认值。

下面是一个简单的例子:

@Component
public class Converter extends AbstractHttpMessageConverter<Object> {

    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    @Inject
    private ObjectMapper objectMapper;

    public Converter(){
        super(MediaType.APPLICATION_JSON_UTF8,
            new MediaType("application", "*+json", DEFAULT_CHARSET));
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    protected Object readInternal(Class<? extends Object> clazz,
                                  HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return objectMapper.readValue(decrypt(inputMessage.getBody()), clazz);
    }

    @Override
    protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
        outputMessage.getBody().write(encrypt(objectMapper.writeValueAsBytes(o)));
    }

    private InputStream decrypt(InputStream inputStream){
        // do your decryption here 
        return inputStream;
    }

    private byte[] encrypt(byte[] bytesToEncrypt){
        // do your encryption here 
        return bytesToEncrypt;
    }
}
 类似资料:
  • 本文向大家介绍SpringBoot中使用com.alibaba.druid.filter.config.ConfigTools对数据库密码加密的方法,包括了SpringBoot中使用com.alibaba.druid.filter.config.ConfigTools对数据库密码加密的方法的使用技巧和注意事项,需要的朋友参考一下 1.在本地Maven仓库中打开Powershell 2.输入命令,然

  • 后台返回的json数据经过Base64加密,js怎么解密? ........

  • > 该服务使用SpringBoot、Maven、MongoDB和Ehcache。 服务需要一个快速且频繁缓存的服务器,所以最终,我选择了Ehcache。 所有缓存都将以几乎相同的频率调用,因此在这种情况下没有热数据或冷数据。 MongoDB中的原始数据每天都会被定时器服务更新,所以我每天要做的就是将所有更新的数据加载到Ehcache中。 这些数据中的每一项都彼此有联系,就像您使用一个来查找另一个的

  • bcrypt 数据加密 文档:https://www.npmjs.com/package/bcryptjs 安装:cnpm i -S bcryptjs [ ] 使用: 封装helper函数 app / extend / helper.js // 引入加密插件 const bcrypt = require('bcryptjs') const jwt = require('jsonwebtoken')

  • EncryptAlgorithm SPI 名称 详细说明 EncryptAlgorithm 数据加密算法 已知实现类 详细说明 MD5EncryptAlgorithm 基于 MD5 的数据加密算法 AESEncryptAlgorithm 基于 AES 的数据加密算法 RC4EncryptAlgorithm 基于 RC4 的数据加密算法 QueryAssistedEncryptAlgorithm S

  • 配置项说明 命名空间:http://shardingsphere.apache.org/schema/shardingsphere/encrypt/encrypt-5.0.0.xsd <encrypt:rule /> 名称 类型 说明 默认值 id 属性 Spring Bean Id queryWithCipherColumn (?) 属性 是否使用加密列进行查询。在有原文列的情况下,可以使用原文