基于CXF的WebService身份认证的访问控制

实现发布服务:

 

package cn.org.coral.biz.examples.webservice;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;

/**
* WebService接口定义类.
*
* 使用@WebService将接口中的所有方法输出为Web Service. 可用annotation对设置方法、参数和返回值在WSDL中的定义.
*/
@WebService
public interface WebServiceSample {

/**
* 一个简单的方法,返回一个字符串
*
*
@param hello
*
@return
*/
public String say(String hello);

}

接口实现类:

 

 

package cn.org.coral.biz.examples.webservice;

import java.util.ArrayList;
import javax.jws.WebService;

/**
* WebService实现类.
*
* 使用@WebService指向Interface定义类即可.
*/
@WebService(endpointInterface
= "cn.org.coral.biz.examples.webservice.WebServiceSample")
public class WebServiceSampleImpl implements WebServiceSample {

public String say(String hello) {
return "hello " + hello;
}

}

服务端配置文件web.xml:

 

<?xml version="1.0" encoding="UTF-8"?>   
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ws-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<display-name>CXF Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

 

ws-context.xml:

 

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
xsi:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd"
default-autowire="byName" default-lazy-init="true">

<http-conf:conduit name="*.http-conduit"><!-- 对所有服务生效 -->
<http-conf:client ConnectionTimeout="10000" ReceiveTimeout="20000"/>
</http-conf:conduit>
<!--
可参考http://jiake.javaeye.com/blog/368735
# ConnectionTimeout WebService以TCP连接为基础,这个属性可以理解为tcp的握手时的时间设置,超过设置的时间长则认为是连接超时.以毫秒为单位,默认是30000毫秒,即30秒.
#
# ReceiveTimeout 这个属性是发送WebService的请求后等待响应的时间,超过设置的时长就认为是响应超时.以毫秒为单位,默认是60000毫秒,即60秒.
-->


<!-- Import apache CXF bean definition -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />


<!-- Define HelloWorld Bean -->
<bean id="WebServiceSample"
class="cn.org.coral.biz.examples.webservice.WebServiceSampleImpl">
</bean>

<jaxws:endpoint id="webServiceSample"
implementor="#WebServiceSample" address="/webServiceSample" >
<jaxws:inInterceptors>
<!-- 通过一个简单的用户口令验证机制来加强一下WebService的安全性: -->
<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="passwordCallbackClass" value="cn.org.coral.biz.examples.webservice.handler.WsInAuthHandler" />
</map>
</constructor-arg>
</bean>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="user" value="server" />
<entry key="passwordCallbackClass" value="cn.org.coral.biz.examples.webservice.handler.WsOutAuthHandler" />
</map>
</constructor-arg>
</bean>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
</jaxws:outInterceptors>
</jaxws:endpoint>

</beans>

然后是WsInAuthHandler类和WsOutAuthHandler类CallbackHandler:

 

 

package cn.org.coral.biz.examples.webservice.handler;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class WsInAuthHandler implements CallbackHandler {

public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback pc
= (WSPasswordCallback) callbacks[0];
if (pc.getIdentifier().equals("admin")) {
if (!pc.getPassword().equals("123456")) {
//身份认证验证,如果密码不是admin,就报出异常
throw new SecurityException("wrong password");
}
}
else {
//用户名不对,只有ws-client才有访问控制的权限
throw new SecurityException("wrong username");
}
}

}

package cn.org.coral.biz.examples.webservice.handler;

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

public class WsOutAuthHandler implements CallbackHandler {

public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc
= (WSPasswordCallback) callbacks[0];
int usage = pc.getUsage();
if (usage == WSPasswordCallback.USERNAME_TOKEN) {
System.out.println(
"USERNAME_TOKEN");
// username token pwd...
//UsernameToken的用户名的密码
pc.setPassword("123456");

}
else if (usage == WSPasswordCallback.SIGNATURE) {
// set the password for client's
// keystore.keyPassword
//密钥库的密码
pc.setPassword("keyPassword");
}
}
}
}

客户端的WsClinetInAuthHandlerWsClinetOutAuthHandler和服务端的CallbackHandler一样,在此略了。

 

接着客户端代码:

 

@Test
public void test(){
System.out.println(
"juint test run!");

JaxWsProxyFactoryBean factory
= new JaxWsProxyFactoryBean();
factory.setServiceClass(WebServiceSample.
class);
factory.setAddress(
"http://127.0.0.1:8080/CXF_lesson06_Security_02/services/webServiceSample");

WebServiceSample webServiceSample
= (WebServiceSample) factory.create();

ClientProxy proxy
= (ClientProxy) Proxy.getInvocationHandler(webServiceSample);
Client client
= proxy.getClient();

Map
<String,Object> outProps = new HashMap<String,Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER,
"admin");
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, WsClinetOutAuthHandler.
class.getName());
client.getOutInterceptors().add(
new SAAJOutInterceptor());
client.getOutInterceptors().add(
new WSS4JOutInterceptor(outProps));

Map
<String, Object> inProps = new HashMap<String, Object>();
inProps.put(
"action", "UsernameToken");
inProps.put(
"passwordType", "PasswordText");
inProps.put(
"passwordCallbackClass", "cn.org.coral.biz.examples.webservice.handler.WsOutAuthHandler");
client.getInInterceptors().add(
new SAAJInInterceptor());
client.getInInterceptors().add(
new WSS4JInInterceptor(inProps));

System.out.println(webServiceSample.say(
"zhangsan"));

}

到此即可:

 

或者写个客户端配置文件wsclient-context.xml:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName" default-lazy-init="true">


<!-- ws clinet -->
<bean id="webServiceSampleClient"
class="cn.org.coral.biz.examples.webservice.WebServiceSample"
factory-bean="webServiceSampleClientFactory" factory-method="create" />


<bean id="webServiceSampleClientFactory"
class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass"
value="cn.org.coral.biz.examples.webservice.WebServiceSample" />
<property name="address"
value="http://127.0.0.1:8080/CXF_lesson06_Security_02/services/webServiceSample" />
<property name="outInterceptors">
<list>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
<ref bean="wss4jOutConfiguration" />
</list>
</property>
<property name="inInterceptors">
<list>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
<ref bean="wss4jInConfiguration" />
</list>
</property>
</bean>

<bean id="wss4jOutConfiguration"
class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<property name="properties">
<map>
<entry key="action" value="UsernameToken" />
<entry key="user" value="admin" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackRef">
<ref bean="passwordCallbackOut" />
</entry>
</map>
</property>
</bean>
<bean id="wss4jInConfiguration"
class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<property name="properties">
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="passwordCallbackRef" >
<ref bean="passwordCallbackIn" />
</entry>
</map>
</property>
</bean>
<bean id="passwordCallbackOut"
class="cn.org.coral.biz.examples.webservice.handler.WsClinetOutAuthHandler">
</bean>

<bean id="passwordCallbackIn"
class="cn.org.coral.biz.examples.webservice.handler.WsClinetInAuthHandler">
</bean>
</beans>

代码:

 

 

@Test
public void testxml(){
ApplicationContext context
= new ClassPathXmlApplicationContext(
"cn/org/coral/biz/examples/webservice/client/wsclient-context.xml");

WebServiceSample webServiceSample
= (WebServiceSample) context.getBean("webServiceSampleClient");
System.out.println(webServiceSample.say(
"luwany"));

}

到此,基本上完成了。

 

说明:此例子是网上看到的的例子,然后写个完整些,以后可以参考下。可能理解得不够深刻。

posted @ 2011-01-09 23:09  浅笑67  阅读(5411)  评论(3编辑  收藏  举报