All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.herodotus.engine.rest.protect.crypto.enhance.DecryptRequestBodyAdvice Maven / Gradle / Ivy

There is a newer version: 3.3.3.2
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2020-2030 郑庚伟 ZHENGGENGWEI (码匠君),  Licensed under the AGPL License
 *
 * This file is part of Herodotus Engine.
 *
 * Herodotus Engine is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Herodotus Engine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 */

package cn.herodotus.engine.rest.protect.crypto.enhance;

import cn.herodotus.engine.assistant.core.json.jackson2.utils.Jackson2Utils;
import cn.herodotus.engine.assistant.core.utils.http.SessionUtils;
import cn.herodotus.engine.rest.core.annotation.Crypto;
import cn.herodotus.engine.rest.core.exception.SessionInvalidException;
import cn.herodotus.engine.rest.protect.crypto.processor.HttpCryptoProcessor;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.TextNode;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.util.ByteUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.Map;

/**
 * 

Description: RequestBody 解密 Advice

* * @author : gengwei.zheng * @date : 2021/10/4 12:15 */ @RestControllerAdvice public class DecryptRequestBodyAdvice implements RequestBodyAdvice { private static final Logger log = LoggerFactory.getLogger(DecryptRequestBodyAdvice.class); private HttpCryptoProcessor httpCryptoProcessor; public void setInterfaceCryptoProcessor(HttpCryptoProcessor httpCryptoProcessor) { this.httpCryptoProcessor = httpCryptoProcessor; } @Override public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { String methodName = methodParameter.getMethod().getName(); Crypto crypto = methodParameter.getMethodAnnotation(Crypto.class); boolean isSupports = ObjectUtils.isNotEmpty(crypto) && crypto.requestDecrypt(); log.trace("[Herodotus] |- Is DecryptRequestBodyAdvice supports method [{}] ? Status is [{}].", methodName, isSupports); return isSupports; } @Override public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type targetType, Class> converterType) throws IOException { String sessionId = SessionUtils.analyseSessionId(httpInputMessage); if (SessionUtils.isCryptoEnabled(httpInputMessage, sessionId)) { log.info("[Herodotus] |- DecryptRequestBodyAdvice begin decrypt data."); String methodName = methodParameter.getMethod().getName(); String className = methodParameter.getDeclaringClass().getName(); String content = IoUtil.read(httpInputMessage.getBody()).toString(); if (StringUtils.isNotBlank(content)) { String data = httpCryptoProcessor.decrypt(sessionId, content); if (StringUtils.equals(data, content)) { data = decrypt(sessionId, content); } log.debug("[Herodotus] |- Decrypt request body for rest method [{}] in [{}] finished.", methodName, className); return new DecryptHttpInputMessage(httpInputMessage, ByteUtil.toUtf8Bytes(data)); } else { return httpInputMessage; } } else { log.warn("[Herodotus] |- Cannot find Herodotus Cloud custom session header. Use interface crypto founction need add X_HERODOTUS_SESSION_ID to request header."); return httpInputMessage; } } private String decrypt(String sessionKey, String content) throws SessionInvalidException { JsonNode jsonNode = Jackson2Utils.toNode(content); if (ObjectUtils.isNotEmpty(jsonNode)) { decrypt(sessionKey, jsonNode); return Jackson2Utils.toJson(jsonNode); } return content; } private void decrypt(String sessionKey, JsonNode jsonNode) throws SessionInvalidException { if (jsonNode.isObject()) { Iterator> it = jsonNode.fields(); while (it.hasNext()) { Map.Entry entry = it.next(); if (entry.getValue() instanceof TextNode t && entry.getValue().isValueNode()) { String value = httpCryptoProcessor.decrypt(sessionKey, t.asText()); entry.setValue(new TextNode(value)); } decrypt(sessionKey, entry.getValue()); } } if (jsonNode.isArray()) { for (JsonNode node : jsonNode) { decrypt(sessionKey, node); } } } @Override public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { return body; } @Override public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { return body; } public static class DecryptHttpInputMessage implements HttpInputMessage { private final HttpInputMessage httpInputMessage; private final byte[] data; public DecryptHttpInputMessage(HttpInputMessage httpInputMessage, byte[] data) { this.httpInputMessage = httpInputMessage; this.data = data; } @Override public InputStream getBody() throws IOException { return new ByteArrayInputStream(this.data); } @Override public HttpHeaders getHeaders() { return this.httpInputMessage.getHeaders(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy