webservice-custom annotation processing parameter encryption and decryption problem
The webservice was used in the previous project, and I knew it before After a bit of apache’s cxf framework, so I used cxf to implement the webservice server. There is no technical difficulty in its implementation, but in order to ensure security, the project adopts the process of transmission encryption, so most of the request parameters need to be encrypted, and the return parameters are also Encryption is required. The general process is:
Request parameter symmetric encryption + symmetric secret key asymmetric encryption,
return parameter stack encryption + symmetric secret key asymmetric encryption
Parameter encryption It is not complicated in itself, but some services do not require encryption, and some do. The encryption tools are not universal.
string, datahandler, etc. cannot be reused. Although the essence is to encrypt byte data, many methods must be written. For method parameters, check the parameters that need to be encrypted and decrypted, and then find the corresponding type to process the method call.
The logic is very clear, but the process is very disgusting. In the end, a version was realized in this way, but it did not suit my intention. p>
If you can get the parameter list in the interceptor, and then find the corresponding decoder to decode, it is relatively simple. But the difficulty is, if the parameter is marked, and the decoder of the marked parameter is specified?
I thought of annotations, annotations can be marked, parameters, and then the annotations can be obtained through reflection, and the content can be parsed.
I originally wanted to mark the parameters, but each of them is too troublesome, and it is not convenient to obtain it. Put it on the method and use the array to receive it.
The problem is solved.
code implementation
Custom annotations:
import java.lang.annotation.ElementType;import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * @author webservice request parameter custom annotation* */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface RequestHanleAnnotation { Class[] handler() default {}; int[] index() default {}; }
Parameter decoder interface
import java.util .Map; import java.util.concurrent.ConcurrentHashMap; /** * @author taoyuan *parameter processor* @param */ public abstract< /span> class ParamHandler<T> { //Decoder instance cache public static final Map hanlers=new ConcurrentHashMap<>(); //processing method abstract T handle(T t);}
The decoder is implemented, there is no real decoding here, but 123 is added after the parameter
public class StringHandler extends ParamHandler<String> { @Override public String handle(String t) {return t+"123";}}
Use of service method annotations
//Indicates that the first parameter needs StringHandler processing @RequestHanleAnnotation(index=0,handler= StringHandler.class) public String test(String test, String test2) throws Exception {System.out.println(test); System.out.println(test2); return "cesshi"; }
Interceptor implementation
import java.io. File; import java.lang.reflect .Method; import java .util.Map; import org. apache.commons.io.FileUtils< /span>; import org.apache.cxf span>.binding.soap.SoapMessage ; import org.apache.cxf< span class="hljs-preprocessor">.interceptor.Fault; import org.apache.cxf.message.MessageContentsList; import org.apache.cxf.phase.AbstractPhaseInterceptor ; import org.apache.cxf. phase.Phase; import org.apache .log4j.Logger; span> import com.alibaba.fastjson .JSON; import com.alibaba.fastjson.JSONObject; /** * @author 都市桃源*/ public class EcrInInterceptor extends AbstractPhaseInterceptor{ private Logger log = Logger.getLogger(ContractLogicImpl.class); public EcrInInterceptor() {// Call the interceptor super(Phase.PRE_INVOKE);} @Override public before calling the method void handleMessage(SoapMessage msg) throws Fault {/*Get the request ip, the interceptor can do unified log processing HttpServletRequest httprequest = (HttpServletRequest)msg.get(AbstractHTTPDestination.HTTP_REQUEST); * */ //Get the method being executed Method method = MsgUtil.getSoapMethod(msg); //Analyze the annotation and process the parameter MessageCo ntentsList contentsList = MessageContentsList.getContentsList(msg); MsgUtil. handle(method,contentsList);} @Override public void handleFault(SoapMessage message) {super.handleFault< /span>(message);}
Annotation parsing tool class implementation
import java.lang.reflect.Method;import java.util. HashMap;import java.util.Map;import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.message.Exchange;import org.apache.cxf.message.MessageContentsList; import org.apache.cxf.service.Service; import org.apache.cxf.service.invoker.MethodDispatcher;import org.apache.cxf.service.model.BindingOperationInfo;/** * @author ll * Get method name* */public class MsgUtil { /**Get the calling method according to the message* @param msg * @return * / public static Method getSoapMethod(SoapMessage msg){ Exchange exchange = msg.getExchange(); BindingOperationInfo bop = exchange.get(BindingOperationInfo.class); MethodDispatcher md = (MethodDispatcher) exchange.get(Service.class) .get(MethodDispatcher.class.getName( )); Method method = md.getMethod(bop); return method;} public static void handle(Method method, MessageContentsList contentsList) {if(method==null)return; RequestHanleAnnotation reqAnno= method.getAnnotation(RequestHanleAnnotation.class); int[] indexes = reqAnno.index(); if( indexs==null||indexs.length==0)return; Class[] handlers = reqAnno.handler(); try {//Handler instance< /span> ParamHandler handler=null; for(int i= 0,len=indexs.length;i//Get the parameters to be processed Object obj = contentsList.get(indexs[i ]); //Get the handler instance from the cache handler=ParamHandler.hanlers.get(handlers[i]); if(handler==null){ //create handler instance handler=(ParamHandler ) handlers[i].newInstance(); //Cache processor instance ParamHandler.hanlers.put(handlers[i], handler);} contentsList.set(indexs [i], handler.handle(obj));} }catch (Exception e) {e.printStackTrace();} }}
The return parameter can also be implemented by annotation, here is I won’t go into details, the implementation is relatively simple.
** It should be noted that the interceptor interception order is different. Interceptors inherit the AbstractPhaseInterceptor class uniformly, request interception: super(Phase.PRE_INVOKE); Return interception: super (Phase.PRE_STREAM);**