Web Service实践——Xfire的ws-security用户名和密码安全验证 - helloklzs - ITeye技术网站
三、服务器端
1、PasswordHandler类,继承自avax.security.auth.callback.CallbackHandler
package com.channelsoft.hr.wssecurity;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
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 PasswordHandler implements CallbackHandler {
@SuppressWarnings("unchecked")
private Map passwords = new HashMap();
@SuppressWarnings("unchecked")
public PasswordHandler() {
passwords.put("server", "serverpass");//服务器端记录的用户名和密码,可以有多个
}
public void handle(Callback[] callbacks) throws IOException,//回调接口方法
UnsupportedCallbackException {
System.out.println("Handling Password!");
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];//获取回调对象
String id = pc.getIdentifer();//获取用户名
System.out.println("id:"+id+" ,password:"+(String) passwords.get(id));
String validPw = (String)password.get(id);②-3:获取用户对应的正确密码
②-4:如果是明文密码直接进行判断
if(WSConstants.PASSWORD_TEXT.equals(callback.getPasswordType())){
String pw = callback.getPassword();
if(pw == null || !pw.equalsIgnoreCase(validPw)){
throw new WSSecurityException("password not match");
}
}else{
pc.setPassword((String) passwords.get(id));//如果是密码摘要,向回调设置正确的密码(明文密码)
}
}
2、service.xml
<beans xmlns="http://xfire.codehaus.org/config/1.0">
<service>
<name>hrwebservice</name>
<namespace>com.channelsoft.hr</namespace>
<serviceClass>com.channelsoft.hr.webservice.DepartmentAndPersonInfo</serviceClass>
<implementationClass>com.channelsoft.hr.webservice.impl.DepartmentAndPersonInfoImpl</implementationClass>
<inHandlers>
<handler handlerClass="org.codehaus.xfire.util.dom.DOMInHandler" />
<bean
class="org.codehaus.xfire.security.wss4j.WSS4JInHandler" xmlns="">
<property name="properties">
<props>
<prop key="action">UsernameToken</prop>//使用用户名与密码进行安全验证
<prop key="passwordCallbackClass">
com.channelsoft.hr.wssecurity.PasswordHandler//回调类
</prop>
</props>
</property>
</bean>
</inHandlers>
</service>
</beans>
四、客户端
1、
1、PasswordHandler类,继承自avax.security.auth.callback.CallbackHandler
package com.channelsoft.hr.wssecurity;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
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 PasswordHandler implements CallbackHandler {
@SuppressWarnings("unchecked")
private Map passwords = new HashMap();
@SuppressWarnings("unchecked")
public PasswordHandler() {
passwords.put("server", "serverpass");//服务器端记录的用户名和密码,可以有多个
}
public void handle(Callback[] callbacks) throws IOException,//回调接口方法
UnsupportedCallbackException {
System.out.println("Handling Password!");
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];//获取回调对象
String id = pc.getIdentifer();//获取用户名
System.out.println("id:"+id+" ,password:"+(String) passwords.get(id));
String validPw = (String)password.get(id);②-3:获取用户对应的正确密码
②-4:如果是明文密码直接进行判断
if(WSConstants.PASSWORD_TEXT.equals(callback.getPasswordType())){
String pw = callback.getPassword();
if(pw == null || !pw.equalsIgnoreCase(validPw)){
throw new WSSecurityException("password not match");
}
}else{
pc.setPassword((String) passwords.get(id));//如果是密码摘要,向回调设置正确的密码(明文密码)
}
}
2、客户端调用
package hr;
import java.net.MalformedURLException;
import org.codehaus.xfire.client.Client;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.security.wss4j.WSS4JOutHandler;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;
import org.codehaus.xfire.transport.http.CommonsHttpMessageSender;
import org.codehaus.xfire.util.dom.DOMOutHandler;
import com.channelsoft.hr.webservice.DepartmentAndPersonInfo;
public class getHRInfo
{
public static void main(String args[])
{
String serviceURL = "http://localhost:8080/HRWebService/services/hrwebservice";
// 创建service对象
Service serviceModel = new ObjectServiceFactory().create(DepartmentAndPersonInfo.class);
XFireProxyFactory serviceFactory = new XFireProxyFactory();
try
{
// 获取服务对象
DepartmentAndPersonInfo service = (DepartmentAndPersonInfo) serviceFactory.create(serviceModel, serviceURL);
// 忽略http连接的超时时间,0为不设置超时时间,》=1为超时毫秒数
Client client = Client.getInstance(service);
client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, "0");
//发送授权信息
// client.addOutHandler(new ClientAuthenticationHandler("abcd","1234"));
// //WS-Security
WSS4JOutHandler wsOut = new WSS4JOutHandler();
String actions =WSHandlerConstants.USERNAME_TOKEN;
wsOut.setProperty(WSHandlerConstants.ACTION, actions);//动作
wsOut.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_DIGEST);//密码类型
wsOut.setProperty(WSHandlerConstants.USER, "server"); //指定用户
wsOut.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordHandler.class.getName());//密码回调类
client.addOutHandler(new DOMOutHandler());
client.addOutHandler(wsOut);
// 调用服务
String hello = service.queryDepartmentInfo();
String hello2 = service.queryPersonnelInfo("", "", "");
System.out.println(hello);
System.out.println(hello2);
}
catch (MalformedURLException e)
{
System.out.println("错误!!!");
e.printStackTrace();
}
}
}
Web Service实践之——XFire实例
转自:http://www.javaeye.com/topic/195927
1、配置XFire运行环境:
在Tomcat下新建一个Web Applications,命名为stove,然后在其WEB-INF目录下新建一个web.xml文件,文件中输入:
Xml代码
<?xml version="1.0" encoding="GB2312">
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>XFireServlet</servlet-name>
<display-name>XFire Servlet</display-name>
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/servlet/XFireServlet/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
其中主要就是引入了XFireServlet,用以处理Web Service请求,并且负责提供Web Service的WSDL,如果你发布了一个名为BookService的WebService,则可以通过网址:
http://<服务器>[:端口]/<webapp名>/services/BookService
来访问这个WebService,并且通过地址:
http://<服务器>[:端口]/<webapp名>/services/BookService?WSDL 来得到这个WebService的WSDL信息。
2、开发最简单的WebService
建一个package:cn.com.pansky.webservice.xfire.study,在这个包下面新建一个接口:
Java代码
package cn.com.pansky.webservice.xfire.study;
public interface SayHiService{
public String sayHi(String name);
}
这个接口是告诉服务器你的WebService哪些方法可以被用户调用的。下面我们再来写一个SayHiService的实现类,以完成业务逻辑:
Java代码
package cn.com.pansky.webservice.xfire.study;
public class SayHiServiceImpl implements SayHiService{
public String sayHi(String name){
if(name==null){
return "连名字也不肯告诉我吗?";
}
return name+", 你吃了吗?没吃回家吃去吧。";
}
public String 不告诉你(){
return "我的名字不告诉你!";
}
} 这个类实现了sayHi方法,该方法是可以通过WebService调用访问到的。另外还实现了一个方法“不告诉你”,该方法因为没有在接口SayHiService中定义,所以不能被WebService调用到。
这个例子足够简单吧,就跟我们刚学Java时写的"Hello world"没什么两样。
到这里为止,我们做的跟平时的Java开发没啥区别,该如何来发布WebService呢?
3、把JAVA类发布为WebService:
在src目录下新建文件夹:META-INF/xfire,然后在该文件夹下新建一个XML文件:services.xml,文件内容如下:
Xml代码
<beans xmlns="http://xfire.codehaus.org/config/1.0">
<service>
<name>SayHiService</name>
<namespace>http://cn.com.pansky/SayHiService</namespace>
<serviceClass>cn.com.pansky.webservice.xfire.study.SayHiService</serviceClass>
<implementationClass>cn.com.pansky.webservice.xfire.study.SayHiServiceImpl</implementationClass>
</service>
</beans>
这个文件定义一个WebService: SayHiService,并同时定义了接口和实现类。
好了,该建的文件基本建完了,现在想办法把src下的java文件编译成class,并复制到WEB-INF/classes目录下
4、启动Tomcat,测试WebService
如果Tomcat还没配置好,抽两分钟再配一下。再把Tomcat启动起来。
再打开浏览器,输入:
http://localhost/stove/services
,服务器返回的结果如下:
Available Services:
* SayHiService [wsdl]
Generated by XFire ( http://xfire.codehaus.org )
我们看到我们的WebService已经布署成功了,我们再看看它的WSDL信息:
这个文件跟我们用Axis生成的基本是一样的。
5、享受美味的时刻
注意:客户端使用WebService接口需要jar包(wsdl4j-1.6.1.jar和xfire-all-1.2.6.jar),缺少wsdl4j-1.6.1.jar时,会出现错误:The type javax.wsdl.Definition cannot be resolved. It is indirectly referenced from required .class files
WebService这道大餐算是烹制好了,现在是享用美餐的时候了。
我们写一个客户端吃掉这道大餐:
Java代码
package cn.com.pansky.webservice.xfire.study;
import java.net.MalformedURLException;
import java.util.Map;
import org.codehaus.xfire.client.Client;
import org.codehaus.xfire.client.XFireProxyFactory;
import org.codehaus.xfire.service.Service;
import org.codehaus.xfire.service.binding.ObjectServiceFactory;
import org.codehaus.xfire.transport.http.CommonsHttpMessageSender;
public class SayHiClient{
public static void main(String args[]) {
String serviceURL = "http://localhost/stove/services/SayHiService";
Service serviceModel = new ObjectServiceFactory().create(SayHiService.class,null,"http://cn.com.pansky/SayHiService",null);
XFireProxyFactory serviceFactory = new XFireProxyFactory();
try{
SayHiService service = (SayHiService) serviceFactory.create(serviceModel, serviceURL);
//忽略http连接的超时时间,0为不设置超时时间,》=1为超时毫秒数
Client client = Client.getInstance(service);
client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, "0");
String hello = service.sayHi("张山疯");
System.out.println("服务器对[张山疯] 的回答是:" + hello );
hello = service.sayHi(null);
System.out.println("服务器胡言乱语说:" + hello );
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
14. Object Relational Mapping (ORM) Data Access - Using sessionFactory getCurrentSession
Implementing DAOs based on plain Hibernate 3 API
Implementing DAOs based on plain Hibernate 3 API
Hibernate 3 has a feature called contextual sessions, wherein Hibernate itself manages one current Session
per transaction. This is roughly equivalent to Spring’s synchronization of one Hibernate Session
per transaction. A corresponding DAO implementation resembles the following example, based on the plain Hibernate API:
public class ProductDaoImpl implements ProductDao { private SessionFactory sessionFactory; public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } public Collection loadProductsByCategory(String category) { return this.sessionFactory.getCurrentSession() .createQuery("from test.Product product where product.category=?") .setParameter(0, category) .list(); } }
This style is similar to that of the Hibernate reference documentation and examples, except for holding the SessionFactory
in an instance variable. We strongly recommend such an instance-based setup over the old-school static
HibernateUtil
class from Hibernate’s CaveatEmptor sample application. (In general, do not keep any resources instatic
variables unless absolutely necessary.)
The above DAO follows the dependency injection pattern: it fits nicely into a Spring IoC container, just as it would if coded against Spring’s HibernateTemplate
. Of course, such a DAO can also be set up in plain Java (for example, in unit tests). Simply instantiate it and call setSessionFactory(..)
with the desired factory reference. As a Spring bean definition, the DAO would resemble the following:
<beans> <bean id="myProductDao" class="product.ProductDaoImpl"> <property name="sessionFactory" ref="mySessionFactory"/> </bean> </beans>
The main advantage of this DAO style is that it depends on Hibernate API only; no import of any Spring class is required. This is of course appealing from a non-invasiveness perspective, and will no doubt feel more natural to Hibernate developers.
However, the DAO throws plain HibernateException
(which is unchecked, so does not have to be declared or caught), which means that callers can only treat exceptions as generally fatal - unless they want to depend on Hibernate’s own exception hierarchy. Catching specific causes such as an optimistic locking failure is not possible without tying the caller to the implementation strategy. This trade off might be acceptable to applications that are strongly Hibernate-based and/or do not need any special exception treatment.
Fortunately, Spring’s LocalSessionFactoryBean
supports Hibernate’s SessionFactory.getCurrentSession()
method for any Spring transaction strategy, returning the current Spring-managed transactional Session
even with HibernateTransactionManager
. Of course, the standard behavior of that method remains the return of the current Session
associated with the ongoing JTA transaction, if any. This behavior applies regardless of whether you are using Spring’s JtaTransactionManager
, EJB container managed transactions (CMTs), or JTA.
In summary: you can implement DAOs based on the plain Hibernate 3 API, while still being able to participate in Spring-managed transactions.