我用xfire做了一个webservice用来往数据库中录入数据,想在其中加入用户身份验证,刚开始学习webservice,不知道xfire是如何来实现webservice的ws-security的,被这个问题困扰了很久,请大家帮忙!

解决方案 »

  1.   

    XFire通过wss4j提供ws-security支持一、    前提条件:前提条件要安装Unlimited Strength Jurisdiction Policy(可以在http://java.sun.com/j2se/1.5.0/download.jsp或http://java.sun.com/j2se/1.4.2/download.html下载)和Bouncy Castle(来自http://BouncyCastle.org)。否则会出现无效算法(algorithm)或Key大小(Key Size)
    为了能支持WS-Security必须添加两个Handler:inhandlers、outhandlers。
    以下必须添加到inHandlers
    1、    org.codehaus.xfire.security.wss4j.WSS4JInHandler:执行WS-Security相关的函数;
    2、    org.codehaus.xfire.util.dom.DOMInHandler:为WS-Security从StAX 转换成DOM格式。
    注:DOMInHandler必须引入Xalan 2.7.0,XFire默认没有引入。
    以下添加到outHandlers:
    1、    org.codehaus.xfire.security.wss4j.WSS4JOutHandler:执行WS-Security相关的函数;
    2、    org.codehaus.xfire.util.dom.DOMOutHandler:为WS-Security从StAX 转换成DOM格式。
    二、    安装Unlimited Strength Jurisdiction Policy和Bouncy Castle
    1、    安装Unlimited Strength Jurisdiction Policy:把local_policy.jar和US_export_policy.jar两个文件拷贝到:C:\j2re1.4.2\lib\security\下;(如果JRE安装在C:\j2re1.4.2)。
    2、    安装Bouncy Castle:
    (1)、把下载的bcprov-jdk14-119.jar文件拷贝到两个地方:
    一个在你安装的JDK目录中,比如:C:\j2sdk1.4.0-rc\jre\lib\ext。另一个在你的JDK运行环境中,比如:C:\Program Files\Java\j2re1.4.0-rc\lib\ext;
    (2)、还要在对两个java.security进行修改:
    我的在 C:\j2sdk1.4.0-rc\jre\lib\security\java.security;C:\Program Files\Java\j2re1.4.0-rc\lib\security\java.security;
      在java.security中加入 security.provider.6=org.bouncycastle.jce.provider.BouncyCastleProvider
    三、    创建密钥:
    1、    通过别名和密码创建私密钥到keystore:
    keytool -genkey -alias ws_security -keypass keypassword -keystore privatestore.jks -storepass keyStorePassword -dname "cn=ws_security" -keyalg RSA
        采用RSA算法进行处理。
    2、    证书:
    keytool -selfcert -alias ws_security -keystore privatestore.jks -storepass keyStorePassword -keypass keypassword
    3、    导出公钥到key.rsa:
    keytool -export -alias ws_security -file key.rsa -keystore privatestore.jks -storepass keyStorePassword
    4、    导入公钥到新的keystore中:
    keytool -import -alias ws_security  -file key.rsa -keystore publicstore.jks -storepass keyStorePassword
    5、    创建insecurity.properties:
    org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
    org.apache.ws.security.crypto.merlin.keystore.type=jks
    org.apache.ws.security.crypto.merlin.keystore.password=keyStorePassword
    org.apache.ws.security.crypto.merlin.alias.password=keypassword
    org.apache.ws.security.crypto.merlin.keystore.alias=ws_security
    org.apache.ws.security.crypto.merlin.file=META-INF/xfire/publicstore.jks
    6、    创建outsecurity.properties:
    org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
    org.apache.ws.security.crypto.merlin.keystore.type=jks
    org.apache.ws.security.crypto.merlin.keystore.password=keyStorePassword
    org.apache.ws.security.crypto.merlin.alias.password=keypassword
    org.apache.ws.security.crypto.merlin.keystore.alias=ws_security
    org.apache.ws.security.crypto.merlin.file=META-INF/xfire/privatestore.jks
    7、    把文件insecurity,outsecurity.properties,privatestore.jks和publicstore.jks复制到META-INF/xfire/下。
    有关keytool的使用说明,请查看以下资料:
    http://www.churchillobjects.com/c/11201e.html
    http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/keytool.html
    http://support.globalsign.net/en/objectsign/java.cfm
      

  2.   

    四、    实例:
    1、    创建服务接口:
    package example.services;
    public interface BookService {
    public String echo(String msg);
    }
    2、    创建服务实现类:
    package example.services;
    public class BookServiceImpl implements BookService {
            public String echo(String msg){
            return msg;
        }
    }
    3、    配制webservices.xml文件:
        <service>
            <name>BookService</name>
            <serviceClass>example.services.BookService</serviceClass>
            <implementationClass>
                example.services.BookServiceImpl
            </implementationClass>
            <style>wrapped</style>
            <use>literal</use>
            <scope>application</scope>
            <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">Signature</prop>
                            <prop key="signaturePropFile">
                                META-INF/xfire/insecurity.properties
                            </prop>
                            <prop key="decryptionPropFile">
                                META-INF/xfire/insecurity.properties
                            </prop>
                            <prop key="passwordCallbackClass">
                                example.ws_security.PasswordHandler
                            </prop>
                        </props>
                    </property>
                </bean>
            </inHandlers>
        </service>4、    创建:
    package example.ws_security;
    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 {
        private Map passwords = new HashMap();    public PasswordHandler() {
            passwords.put("ws_security", "keypassword");
        }    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));
            pc.setPassword((String) passwords.get(id));
        }
    }
    5、    客户端实现:
    package example.test;import java.lang.reflect.Proxy;
    import java.net.MalformedURLException;import org.apache.ws.security.WSConstants;
    import org.apache.ws.security.handler.WSHandlerConstants;
    import org.codehaus.xfire.client.Client;
    import org.codehaus.xfire.client.XFireProxy;
    import org.codehaus.xfire.client.XFireProxyFactory;
    import org.codehaus.xfire.security.wss4j.WSS4JOutHandler;
    import org.codehaus.xfire.service.Service;
    import org.codehaus.xfire.service.binding.ObjectServiceFactory;
    import org.codehaus.xfire.util.dom.DOMOutHandler;import example.services.BookService;
    import example.ws_security.PasswordHandler;public class TTTest {
        private WSS4JOutHandler wsOut;
        private Service service;
        private BookService bookservice;
        private Client client;
        private static final String SERVICE_URL ="http://localhost:8080/TT/services/BookService";
        public TTTest()
        {
            //建议采用此种方式进行创建服务(带有服务名,此例为“BookService”)
            service=new ObjectServiceFactory().create(BookService.class,
                    "BookService",
                    null,
                    null);
            try {
                bookservice=(BookService) new XFireProxyFactory().create(service, SERVICE_URL);
                client = ((XFireProxy) Proxy.getInvocationHandler(bookservice)).getClient();
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
            
            wsOut = new WSS4JOutHandler();        
            wsOut.setProperty(WSHandlerConstants.SIG_PROP_FILE, "META-INF/xfire/outsecurity.properties");
            wsOut.setProperty(WSHandlerConstants.ENC_PROP_FILE, "META-INF/xfire/outsecurity.properties");
            wsOut.setProperty(WSHandlerConstants.USER, "ws_security");
            //wsOut.setProperty("password", "keypassword11");
            wsOut.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
            wsOut.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordHandler.class.getName());
            wsOut.setProperty(WSHandlerConstants.SIG_KEY_ID,"IssuerSerial");        
            
            client.addOutHandler(new DOMOutHandler());
            client.addOutHandler(wsOut);        String actions =WSHandlerConstants.SIGNATURE;  
            //wsOut.setProperty(WSHandlerConstants.TTL_TIMESTAMP,"30");
            wsOut.setProperty(WSHandlerConstants.ACTION, actions);
            System.out.println(bookservice.echo("Client test msg"));
            client.close();
        }
        public static void main(String [] args)
        {
            new TTTest();
        }
    }
      

  3.   

    谢谢1楼的指点,这个方法我也曾经尝试过,但是在运行客户端调用服务端的时候会提示
    找不到org.apache.ws.security.components.crypto.Merlin ,也就是insecurity.properties和outsecurity.properties文件中的那个org.apache.ws.security.crypto.provider,但是实际上我已经在项目中导入了这个类,而且客户端在获取properties的过程中也能找到这个类,可是一调用服务,就报错class not found,请指教!
      

  4.   

     出错内容
     org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: org.apache.ws.security.components.crypto.Merlin  Not Found
      

  5.   

    bobfallen还在吗
    或者先给我说一下xfire的客户端的ws-security该如何来实现好吗,如果我用c#.net来写一个客户端调用xfire实现的服务端,能否实现ws-security呢,请指教了
      

  6.   

    org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: org.apache.ws.security.components.crypto.Merlin  Not Found
    应该是服务端缺少xalan.jar
      

  7.   

    org.codehaus.xfire.XFireRuntimeException: Could not invoke service.. Nested exception is org.codehaus.xfire.fault.XFireFault: org.apache.ws.security.components.crypto.Merlin  Not Found 
    应该是服务端缺少xalan.jar调用服务端方法以后好像还没有连接到服务器就已经报错了,服务器就算没有启动也是报同样的错误,好像跟服务端没有关系...
      

  8.   

    public void ws_test(){
         srvcModel = new ObjectServiceFactory().create(IHelloWebService.class);   
            XFireProxyFactory factory = new XFireProxyFactory(XFireFactory.newInstance().getXFire());   
            String URL = "http://192.168.0.248:7001/wsTest/services/HelloWebService";
            //String actions=WSHandlerConstants.ENCRYPT;;
            try{
             IHelloWebService srvc = (IHelloWebService) factory.create(srvcModel,URL);   
                client = ((XFireProxy) Proxy.getInvocationHandler(srvc)).getClient();
                
                wsOut = new WSS4JOutHandler();
                Properties properties = new Properties();      
                String actions =WSHandlerConstants.SIGNATURE;   
                wsOut.setProperty(WSHandlerConstants.USER,"ws_security");   
                wsOut.setProperty(WSHandlerConstants.SIG_PROP_FILE,"outsecurity.properties");   
                wsOut.setProperty(WSHandlerConstants.ENC_PROP_FILE,"/outsecurity.properties");   
               properties.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);   
                wsOut.setProperty(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordHandler.class.getName());   
                wsOut.setProperty(WSHandlerConstants.SIG_KEY_ID,"IssuerSerial");       
                
                client.addOutHandler(new DOMOutHandler());
                client.addOutHandler(wsOut); 
                
                wsOut.setProperty(WSHandlerConstants.TTL_TIMESTAMP,"30");   
                wsOut.setProperty(WSHandlerConstants.ACTION,actions);
                
                //String[] ids=srvc.getIds(1000);
                for(int i=1;i<=1000;i++){
                 //ArrayOfString wow=new ArrayOfString();
                 String[] wsdata={String.valueOf(i*2-1),null,String.valueOf(i*10-7),"中国","cao"};
         String[] wowdata={"往日","cao",String.valueOf(i),String.valueOf(i*2),String.valueOf(i*2+21)};
         srvc.insData(wsdata, "4", "ws",username,password);
         srvc.insData(wowdata, "3", "wow",username,password);

         System.out.println("---- "+i+" ----");
                }
                client.close();
                System.out.println("finished!");
            }catch(Exception e){
             System.out.println("客户端调用出错:"+e);
            }
        }
    这是我的客户端测试方法,红色的是服务端接口类,运行到蓝色处就会报错,如果把绿色部分注释掉就能连接到服务端