Codehaus XFire
DocumentationQuicklinksDevelopers
Sponsors |
XFireServletThe core of the HTTP Transport takes place in the XFireServletController. Your own servlets can delegate appropriate requests to this class or you can use one of XFire's internal servlet classes. The XFireServlet is just a thin wrapper for the controller. The XFireServletController provides an xml configuration layer on top of this. XFire also provides the XFireConfigurableServlet which reads the services.xml format automatically for you and the XFireSpringServlet which provides Spring integration. HttpServletRequest/HttpServletResponseThe HttpServletRequest/HttpServletResponse can be accessed via the XFireServletController. HttpServletRequest request = XFireServletController.getRequest(); HttpServletResponse response = XFireServletController.getResponse(); This method will work all the XFire servlets (XFireServlet, XFireConfigurableServlet, XFireSpringServlet). Client AuthenticationThe Apache Jakarta HttpClient is used under the covers to provide HTTP client support. There are two ways which you can override the HttpClient settings: 1. You can set the USERNAME/PASSWORD // Create your client Client client = ....; // Or get it from your proxy Client client = Client.getInstance(myClientProxy); client.setProperty(Channel.USERNAME, "username"); client.setProperty(Channel.PASSWORD, "pass"); 2. You can supply your own HttpClientParms client.setProperty(CommonsHttpMessageSender.HTTP_CLIENT_PARAMS, myParams); The HTTPClient javadocs provide information on how to configure the HttpClientParams. Client connecting to SSL Server via HTTPSIf your webservice is on a HTTPS URL then transport-layer (as opposed to message layer) encryption via SSL will be used. (See your web container's documentation, e.g. Tomcat's, on how to enable SSL on it; this section describes how to connect to such a server, not how to set up that server.) If the SSL certificate of the server is "CArtel" signed (i.e. issued by Verisign, Thawte, etc.) all is well, as Java (JSSE) recognizes such certificates, because their root certs are in your JRE's lib/security/cacerts truststore. If however the server uses a self-signed certificate (or one signed by an in-house CA) you'll run into problems with messages like "ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target". (This is fairly common, particularly in development; and including e.g. a default installation of a commercial application server such as BEA's or IBM's.) There are several ways around this: 1. The "traditional" solution is to add the server certificate to a truststore using the JDK keytool, and then specifiy the global Java system property javax.net.ssl.trustStore to point to that file. ProtocolSocketFactory easy = new EasySSLProtocolSocketFactory(); Protocol protocol = new Protocol("https", easy, 8443); Protocol.registerProtocol("https", protocol); 3. However, the EasySSLProtocolSocketFactory explicitly says in its JavaDoc that: "This socket factory SHOULD NOT be used for productive systems due to security reasons, unless it is a concious decision and you are perfectly aware of security implications of accepting [all] self-signed certificates.". A better way might be to accept just that one self-signed certificate, or all certificates signed by an in-houce CA. Indeed, the not-yet-commons-ssl library has a programmatic solution for this, using the following few lines: (You'll need to download not-yet-commons-ssl from http://juliusdavies.ca/commons-ssl/ for this code.) // Technique similar to http://juliusdavies.ca/commons-ssl/TrustExample.java.html HttpSecureProtocol protocolSocketFactory = new HttpSecureProtocol(); // "/thecertificate.cer" can be PEM or DER (raw ASN.1). Can even be several PEM certificates in one file. TrustMaterial trustMaterial = new TrustMaterial(getClass().getResource("/thecertificate.cer")); // We can use setTrustMaterial() instead of addTrustMaterial() if we want to remove // HttpSecureProtocol's default trust of TrustMaterial.CACERTS. protocolSocketFactory.addTrustMaterial(trustMaterial); // Maybe we want to turn off CN validation (not recommended!): protocolSocketFactory.setCheckHostname(false); Protocol protocol = new Protocol("https", (ProtocolSocketFactory) protocolSocketFactory, 8443); Protocol.registerProtocol("https", protocol); This is of course similar to 1. but avoids dealing with a global Java system property that other code may also depends on and a filename, e.g. you can the certificate in a classpath resource as well. -- If you don't have a .cer (same as a .pem) file of your server, the openssl tool (available from Cygwin under Windows) will fetch it. Not-yet-commons-ssl.jar also contains a command-line tool for fetching the certificate. openssl s_client -showcerts -prexit -connect myhost.mydomain:port
# not-yet-commons-ssl.jar can do the same thing:
java -jar not-yet-commons-ssl-0.3.7.jar -t myhost.mydomain:port
This will have openssl print the certificate(s) of that web server; you can copy/paste the relevant (or certificate lines between (and including) the BEGIN/END CERTIFICATE lines into some thecertificate.cer text file. (BTW: Make sure there is a no trailing carriage return after the END line, else Java's keytool will have trouble with the file, in case you are planning to import it to a truststore.) Security note: downloading the certificate directly from the SSL handshake using "openssl s_client" or "not-yet-commons-ssl.jar" is not safe. In a dev environment it's okay. But in a production environment it leaves you susceptible to the oft-cited man-in-the-middle. It's safer than EasySSLSockeyProtocolFactory because you only download the certificate one time, whereas EasySSLSockeyProtocolFactory is always vulnerable, with every socket created. But nonetheless you should try to acquire the self-signed certificate through a different medium, maybe email (with encryption?), fax, telephone, letter mail, usb-drive, etc. Or if the self-signed cert is hosted on a properly signed "https" site, that's also okay (e.g. https://trustedsite.com/path/to/self-signed.pem). 4.Currently the code above allows for the user to establish an HTTPS connection with the server, but it does not account for sending a client certificate for mutual authentication. To send a client certificate for mutual certificate authentication, you can add the code below. The myKeystore.key file contains your private key and the certificate provided by your CA. For more details on using EasySSLProtocolSocketFactory for your clients, you can visit their examples page: Examples char[] keytStorePass = new String("changeit").toCharArray(); KeyMaterial key = new KeyMaterial(new File("myKeystore.key"), keyStorePass); protocolSocketFactory.setKeyMaterial(key); Proxy SupportProxy support looks very similar to the username/password scenario: // Create your client Client client = ....; // Or get it from your proxy Client client = Client.getInstance(myClientProxy); client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_HOST, "host"); client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_PORT, "8080"); Proxy AuthenticationTo use proxy authentication you need to use following code : // Create your client Client client = ....; // Or get it from your proxy Client client = Client.getInstance(myClientProxy); client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_HOST, "host"); client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_PORT, "8080"); client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_USER, "proxyuser"); client.setProperty(CommonsHttpMessageSender.HTTP_PROXY_PASS, "proxypassword"); HTTP ChunkingYou'll need to enable HTTP chunking on the client if you are sending large files which can't be cached in memory: import org.codehaus.xfire.transport.http.HttpTransport; Client client = ....; client.setProperty(HttpTransport.CHUNKING_ENABLED, "true"); |