programing

스프링 부트 - JSON 데이터 암호화

magicmemo 2023. 7. 25. 20:51
반응형

스프링 부트 - JSON 데이터 암호화

애플리케이션에서 우리는 각 요청 및 응답에 대한 Json 속성 값(속성 이름이 아님)을 암호화/암호 해독해야 합니다.예,
{"userName":"encrypted value", "email":"encrypted value"}

우리는 Sprint 부팅 1.3을 사용하고 @RequestBody@ResponseBody 주석을 사용하여 요청 json을 개체와 바인딩하고 응답 개체를 JSON으로 직렬화합니다.

각 컨트롤러 방법에서 암호화/암호 해독 방법을 호출하지 않습니다.요청 객체와 바인딩하기 전에 스프린트에게 json 값을 해독하도록 지시할 수 있는 방법이 있습니까?마찬가지로, 응답 객체 필드 값을 json으로 변환하기 전에 암호화하시겠습니까?아니면 잭슨을 커스터마이징하는 것이 도움이 될까요?

감사합니다!

자신만의 http 메시지 변환기를 작성할 수 있습니다.스프링 부트를 사용하고 있기 때문에 매우 쉬울 것입니다. 사용자 정의 컨버터를 다음에서 확장하기만 하면 됩니다.AbstractHttpMessageConverter그리고 수업에 점수를 매깁니다.@Component주석

스프링 문서에서:

스프링 부트 컨텍스트에서 해당 유형의 콩을 추가하기만 하면 추가 변환기를 제공할 수 있습니다.추가하는 빈이 기본적으로 포함되었을 유형인 경우(예: MappingJackson2)그러면 JSON 변환용 HttpMessageConverter)가 기본값을 바꿉니다.

여기 간단한 예가 있습니다.

@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;
    }
}

네, 그래서 @eparvan의 답변을 사용했고 수정을 거의 하지 않았습니다.

  1. JSON 응답을 암호화하고 프런트엔드에서 요청 매개 변수를 해독하는 구성 요소를 만듭니다.

저는 이와 같은 "data" 객체의 암호화된 형식의 요청 매개 변수를 가져오고 데이터 객체와 동일한 방식으로 암호화된 응답을 보내고 있습니다.

참조 응답: {"data": "requestOrResponseIn암호화된 개인 키 사용"}

    @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;
        }
    }
  1. 다음은 암호화 및 암호 해독이 진행되는 내 EncryptDecrypt 클래스입니다.

    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;
        }
    

    }

그리고 당신은 끝났어요!

언급URL : https://stackoverflow.com/questions/40740771/spring-boot-encrypt-json-data

반응형