cxf安全认证

我们在使用Web Service的过程中,很多情况是需要对web service请求做认证的,特别涉及到外部系统的调用,那么cxf

 

的认证就显得的特别的重要。cxf的认证大致可以分为:soapHeader认证,WS-Security 校验等等。

 

A cxf中的soapheader认证。

 

基本的原理:客户端在soapHeader中添加header信息,在服务器端通过读取header中的信息来进行验证。

 

在前面的博客中已经编写了相关的cxf的服务端,所以采用http://liuwuhen.iteye.com/admin/blogs/1666189博客中

 

所产生的服务端。

 

实现soapheader认证基本步骤如下:

 

服务端 

 

1.服务端添加soapHeader认证的拦截器,该类继承的是AbstractPhaseInterceptor,其相关代码如下:

public class AuthIntercetpr extends AbstractPhaseInterceptor<SoapMessage> {
 private SAAJInInterceptor saa = new SAAJInInterceptor();

 public AuthIntercetpr() {
  super(Phase.PRE_INVOKE);
  getAfter().add(SAAJInInterceptor.class.getName());
 }

 @Override
 public void handleMessage(SoapMessage message) throws Fault {
  SOAPMessage mess = message.getContent(SOAPMessage.class);
  if (mess == null) {
   saa.handleMessage(message);
   mess = message.getContent(SOAPMessage.class);
  }
  try {
   SOAPHeader head = mess.getSOAPHeader();
   if (head == null) {
    return;
   }
   // 读取自定义的节点
   NodeList nodes = head.getElementsByTagName("tns:spId");
   NodeList nodepass = head.getElementsByTagName("tns:spPassword");
   // 获取节点值,简单认证
   if (nodes.item(0).getTextContent().equals("admin")) {
    if (nodepass.item(0).getTextContent().equals("password")) {
     System.out.println("认证成功");
    }
   } else {
    SOAPException soapExc = new SOAPException("认证错误");
    throw new Fault(soapExc);
   }
  } catch (SOAPException e) {
   e.printStackTrace();
  } catch (Exception e) {
   SOAPException soapExc = new SOAPException("认证错误");
   throw new Fault(soapExc);
  }
 }
}

 

 

2.修改cxf配置文件,在接口发布中添加soapheader认证的拦截器,其配置如下:

 

<jaxws:endpoint id="helloWorld" implementor="com.liuwuhen.cxf.HelloWorldImpl"
   address="/sayHello" wsdlLocation="WEB-INF/HelloWorld.wsdl">
  <jaxws:inInterceptors>
     <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
     <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
     <bean class="com.liuwuhen.cxf.AuthIntercetpr" />
  </jaxws:inInterceptors>
 </jaxws:endpoint>

 

 

服务端的soapheader认证的代码基本完成。

 

客户端 

 

编写客户端,我们需要在客户端添加相关的soapheader信息,这个步骤也需要在拦截器中完成,具体代码如下:

 

public class SoapInterceptor extends AbstractSoapInterceptor {
 private static String nameURI = "http://localhost:8080/cxf-test/services/sayHello";
 public SoapInterceptor() {
  // 指定该拦截器在哪个阶段被激发
  super(Phase.WRITE);
 }
 @Override
 public void handleMessage(SoapMessage message) throws Fault {
  String spPassword = "password";
  String spName = "admin";
  QName qname = new QName("RequestSOAPHeader");
  Document doc = DOMUtils.createDocument();
  // 自定义节点
  Element spId = doc.createElement("tns:spId");
  spId.setTextContent(spName);
  // 自定义节点
  Element spPass = doc.createElement("tns:spPassword");
  spPass.setTextContent(spPassword);

  Element root = doc.createElementNS(nameURI, "tns:RequestSOAPHeader");
  root.appendChild(spId);
  root.appendChild(spPass);

  SoapHeader head = new SoapHeader(qname, root);
  List<Header> headers = message.getHeaders();
  headers.add(head);
 }

}

 

2.在测试客户端的代码中添加soapheader拦截器,即可。

public static void main(String [] args)

{

        

      List list = new ArrayList();

      SoapInterceptor saopInterceptor = new SoapInterceptor();

      list.add(saopInterceptor);

      JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
       // 注册WebService接口
       factory.setServiceClass(IHelloWorld.class);

       // webservice请求地址
       String wsdlAdder = "http://localhost:8080/cxf-test/services/sayHello";
        // 发布接口
      factory.setAddress(wsdlAdder);
      factory.setOutInterceptors(list);
      IHelloWorld helloWorld = (IHelloWorld) factory.create();
      helloWorld.sayHello("cxf hello");

}

 

3.运行客户端代码如果认证成功,即可输出 say hello ,如果认证失败,即抛出相关的异常提示信息。

 

 

B.cxf中的WS-Security认证可以分为:定牌值认证,签名,密钥加密认证等。

 

 

UsernameToken(定牌值认证)

 

关于定牌值认证的实现,服务端需要添加用户名和密码的校验。

 

服务端

 

1.服务端添加用户名和密码的认证类。

public class ServerCallback implements CallbackHandler {

 @Override
 public void handle(Callback[] callbacks) throws IOException,
   UnsupportedCallbackException {
  WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
  String pw = pc.getPassword();
  String idf = pc.getIdentifier();
  if (pw.equals("password") && idf.equals("admin")) {
   System.out.println("success.....");
  } else {
   throw new SecurityException("验证失败");
  }
 }

}

 

2.在cxf配置文件中添加WSS4JInInterceptor配置,具体如下:

 

<jaxws:inInterceptors>
 <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
  <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
    <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
   <constructor-arg>
    <map>
     <entry key="action" value="UsernameToken" />
     <entry key="passwordType" value="PasswordText" />
     <entry key="user" value="cxfServer" />
     <entry key="passwordCallbackRef">
      <ref bean="serverPasswordCallback" />
     </entry>
    </map>
   </constructor-arg>
  </bean>

 </jaxws:inInterceptors>

 

<bean id="serverPasswordCallback" class="com.liuwuhen.cxf.ServerCallback" />

 

 

服务端的代码编写完成。

 

客户端

 

1.客户端设置相关的用户名和密码。

 

public class ClientCallback implements CallbackHandler {

 @Override
 public void handle(Callback[] callbacks) throws IOException,
   UnsupportedCallbackException {
  for (int i = 0; i < callbacks.length; i++) {
   WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
   pc.setPassword("password");
   pc.setIdentifier("admin");
  }
 }
}

 

2.编写客户端相关测试代码。

 

public static void main(String[] args)
{
  List list = new ArrayList();
  SoapInterceptor saopInterceptor = new SoapInterceptor();
  Map<String, Object> properties = new HashMap<String, Object>();
  properties.put(WSHandlerConstants.ACTION,
    WSHandlerConstants.USERNAME_TOKEN);
  properties.put(WSHandlerConstants.USER, "cxfClient");
  properties.put(WSHandlerConstants.PASSWORD_TYPE, "PasswordText");
  properties.put(WSHandlerConstants.PW_CALLBACK_CLASS,
    ClientCallback.class.getName());
  WSS4JOutInterceptor wss4jOutInterceptor = new WSS4JOutInterceptor(
    properties);
  LoggingOutInterceptor loggingOutInterceptor = new LoggingOutInterceptor();
  SAAJOutInterceptor saajOutInterceptor = new SAAJOutInterceptor();
  list.add(saopInterceptor);
  list.add(wss4jOutInterceptor);
  list.add(saajOutInterceptor);
  list.add(loggingOutInterceptor);
  JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
  // 注册WebService接口
  factory.setServiceClass(IHelloWorld.class);
  // webservice请求地址
  String wsdlAdder = "http://localhost:8080/cxf-test/services/sayHello";
  // 发布接口
  factory.setAddress(wsdlAdder);
  factory.setOutInterceptors(list);
  IHelloWorld helloWorld = (IHelloWorld) factory.create();
  helloWorld.sayHello("cxf hello");
}

 

运行相关客户端代码,如果认证成功即可输出success.. say hello,如果认证失败则抛出异常,显示校验失败。

 

 

C.关于cxf的签名和密钥加密的方法,在cxf的官网网站中有详细的介绍,其网址如下:

 

http://cxf.apache.org/docs/ws-security.html

 

 

关于cxf中的https单向认证和https双向认证可以参考我关于cxf的其他文章。 

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值