您的位置:首页 > 运维架构 > Apache

webservice-自定义注解处理参数加解密问题

2017-08-05 19:48 190 查看

webservice-自定义注解处理参数加解密问题

前一段项目中用到了webservice,正好自己之前也了解过一点apache的cxf框架,所以就采用了cxf来实现webservice服务端,本身实现并没技术难点,但是项目为了保证安全性,采用了传输加密的过程,所以大部分请求参数需要加密,返回参数也需要加密,大致流程是:

请求参数对称加密+对称秘钥非对称加密,

返回参数堆成加密+对称秘钥非对称加密

参数加密本身并不复杂,但是有些服务并不需要加密,有些则需要,加密工具类并不通用

string,datahandler等不能重用,虽然本质都是对字节数据加密,但是要写许多方法,还要方法参数,检查需要加解密处理的参数,然后寻找对应的类型处理方法调用.

逻辑很清晰,但是过程实现很恶心,最终这样实现了一版,但是并不合我的意.

如果能在拦截器中获取到参数列表,然后寻找对应的解码器解码,这样就比较简单了.但是难点是,如果标记参数,并指定被标记参数的解码器尼?

我想到了注解,注解就可以标记,参数,然后通过反射获取到注解,解析出内容.

本来想标记到参数上,但是一个个标记太麻烦,而且获取也不太方便,索性就放在方法上,用数组来接收.

问题解决.

代码实现

自定义注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* @author webservice请求参数自定义注解
*
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestHanleAnnotation {
Class[] handler() default {};
int[] index() default {};

}


参数解码器接口

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
* @author taoyuan
*参数处理器
* @param <T>
*/
public abstract class  ParamHandler<T> {
//解码器实例缓存
public static final Map<Class,ParamHandler> hanlers=new ConcurrentHashMap<>();
//处理方法
abstract T handle(T t);
}


解码器实现,这里并没有真正解码,只是在参数后面加了123

public class StringHandler extends ParamHandler<String> {

@Override
public String handle(String t) {
return t+"123";
}

}


服务方法注解使用

//表示第一个参数需要StringHandler处理
@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";

}


拦截器实现

import java.io.File;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.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;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
* @author 都市桃源
*/
public class EcrInInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
private Logger log = Logger.getLogger(ContractLogicImpl.class);
public EcrInInterceptor(){
// 在调用方法之前调用拦截器
super(Phase.PRE_INVOKE);
}

@Override
public void handleMessage(SoapMessage msg) throws Fault {

/*获取请求ip,拦截器中可以做下统一日志处理
HttpServletRequest httprequest = (HttpServletRequest)msg.get(AbstractHTTPDestination.HTTP_REQUEST);

*
*/
//获取正在执行的方法
Method method = MsgUtil.getSoapMethod(msg);
//解析注解,并处理参数
MessageContentsList contentsList = MessageContentsList.getContentsList(msg);
MsgUtil.handle(method,contentsList);

}

@Override
public void handleFault(SoapMessage message) {
super.handleFault(message);
}


注解解析工具类实现

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
* 获取方法名称
*
*/
public class MsgUtil {
/**根据消息获取调用方法
* @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[] indexs = reqAnno.index();
if(indexs==null||indexs.length==0)return;
Class[] handlers = reqAnno.handler();
try {
//处理器实例
ParamHandler handler=null;
for(int i=0,len=indexs.length;i<len;i++){
//获取需要处理的参数
Object obj = contentsList.get(indexs[i]);
//从缓存中获取处理器实例
handler=ParamHandler.hanlers.get(handlers[i]);
if(handler==null){
//创建处理器实例
handler=(ParamHandler) handlers[i].newInstance();
//缓存处理器实例
ParamHandler.hanlers.put(handlers[i], handler);
}
contentsList.set(indexs[i], handler.handle(obj));
}
}catch (Exception e) {
e.printStackTrace();
}

}

}


返回参数同样也可以注解实现,这里就不在赘述了,实现也比较简单.

**需要注意的是,拦截器拦截顺序不一样

拦截器统一继承

AbstractPhaseInterceptor类,

请求拦截 :super(Phase.PRE_INVOKE);

返回拦截: super(Phase.PRE_STREAM);**
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  apache 解密 web service
相关文章推荐