CXF 封装的接口,不希望对外暴露 WSDL结构,找到的CXF安全认证技术都是基于拦截器,在调用的时候返回认证错误信息, 不能保护WSDL不被看到,后来看到别人的一个实现方式最简单有效,基于URL拦截的安全保护,用FILTER。现在把这2种安全保护都记录下来,备用。
WSDL保护:
参考:http://www.myexception.cn/open-source/1505475.html
FILTER:
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest httpRequest = (HttpServletRequest)request;
Enumeration<String> enumeration = httpRequest.getParameterNames();
while (enumeration.hasMoreElements()) {
String param = (String) enumeration.nextElement();
// 查找是否含有参数wsdl,因为使用WSDL也可以,所以这里比较时必须不区分大小写
if (StringUtils.endsWithIgnoreCase("wsdl", param)) {
response.getOutputStream().write("Servlet不存在".getBytes());
return;
}
}
chain.doFilter(request, response);
}
配置的FILTER:
<url-pattern>/pe/*</url-pattern>
注:开始的时候配置的项目名/PEService ,地址是:http://localhost:8080/PEService/getResponse发现拦截不到,这个Servlet配置的名称只能拦截到项目名称之后的地址,即http://localhost:8080/PEService/之后的路径才能匹配,于是重新配置发布的地址<jaxws:endpoint id="getresponse" address="/pe/getResponse"
拦截/pe/*,成功匹配。
试图访问?WSDL结尾的地址都被拦截。
CXF安全认证参考:http://blog.youkuaiyun.com/hujiao_jingling/article/details/7239997
package com.hy;
import java.util.List;
import javax.xml.soap.SOAPException;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.XMLUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class AuthIntercetpr extends AbstractPhaseInterceptor<SoapMessage> {
//private static final Logger logger = Logger.getLogger(AuthIntercetpr.class);
public static final String xml_namespaceUR_att = "http://gd.chinamobile.com//authentication";
public static final String xml_header_el = "soap:Header";
public static final String xml_authentication_el = "auth:authentication";
public static final String xml_systemID_el = "auth:systemID";
public static final String xml_userID_el = "auth:userID";
public static final String xml_password_el = "auth:password";
public AuthIntercetpr() {
// 指定该拦截器在哪个阶段被激发
super(Phase.READ);
}
// 处理消息
public void handleMessage(SoapMessage message) {
//logger.info("==================SoapMessage =" + message);
// 获取SOAP消息的全部头
String method = (String)message.get(Message.HTTP_REQUEST_METHOD);
List<Header> headers = message.getHeaders();
if (null == headers || headers.size() < 1) {
throw new Fault(new SOAPException("SOAP消息头格式不对哦!"));
}
for (Header header : headers) {
SoapHeader soapHeader = (SoapHeader) header;
// 取出SOAP的Header元素
Element element = (Element) soapHeader.getObject();
//logger.info("ELEMENT =" + element.toString());
XMLUtils.printDOM(element);
NodeList userIdNodes = element
.getElementsByTagName(xml_userID_el);
NodeList pwdNodes = element
.getElementsByTagName(xml_password_el);
NodeList systemIdNodes = element
.getElementsByTagName(xml_systemID_el);
/*logger.info("############ 打印帐号信息 ##############");
logger.info(userIdNodes.item(0) + "="
+ userIdNodes.item(0).getTextContent());
logger.info(systemIdNodes.item(0) + "="
+ systemIdNodes.item(0).getTextContent());
logger.info(pwdNodes.item(0) + "="
+ pwdNodes.item(0).getTextContent());
logger.info("############————————##############");*/
if (null != userIdNodes
&& userIdNodes.item(0).getTextContent().equals("test") ) {
if (null != pwdNodes
&& pwdNodes.item(0).getTextContent().equals("test")) {
//logger.info("$$$$$$$$ 认证成功");
} else {//认证失败则抛出异常,停止继续操作
SOAPException soapExc = new SOAPException("阁下可能不是合法用户!");
throw new Fault(soapExc);
}
} else {//认证失败则抛出异常,停止继续操作
SOAPException soapExc = new SOAPException("阁下可能不是合法用户!");
throw new Fault(soapExc);
}
}
}
}
将该类配置到CXF中:
<!--拦截器--> <bean id="authIntercetpr" class="com.hy.AuthIntercetpr"></bean> <!-- 上面不用管 ,id随意,implementor是实现类,address在客户端的地址中会用到--> <jaxws:endpoint id="getresponse" implementor="com.hy.TestImpl" address="/pe/getResponse" publish="false"> <jaxws:inInterceptors> <!-- 在此配置调用当前ws所触发的拦截器--> <ref bean="authIntercetpr" /> </jaxws:inInterceptors> </jaxws:endpoint>
访问调用地址http://localhost:8080/PEService/pe/getResponse报错:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <soap:Fault> <faultcode>soap:Server</faultcode> <faultstring>SOAP消息头格式不对哦!</faultstring> </soap:Fault> </soap:Body> </soap:Envelope>