HTTPS + Basic Auth: Java vs Ruby
For the past couple of weeks I've been working on automating the process of creating an OVA. I considered various tools for the automation but for various reasons that aren't especially relevant here, I ended up going with rake running on top of JRuby. Net result is that for most of the logic I'm writing I have the option of doing it the Java way or the Ruby way. Almost without fail I found myself preferring the more concise Ruby solutions.
Then I found myself needing to do an HTTP GET with basic authentication over HTTPS and verify the server's SSL certificate. Here's the interesting bits of the rakefile with the Java solution:
require 'java'
java.lang.System.setProperty('javax.net.ssl.trustStore', 'mykeystore')
java.lang.System.setProperty('javax.net.ssl.trustStorePassword', 'password')
class MyAuthenticator < java.net.Authenticator
def getPasswordAuthentication()
java.net.PasswordAuthentication.new('userid', java.lang.String.new('password').toCharArray())
end
end
java.net.Authenticator.setDefault(MyAuthenticator.new())
task :testjava do
huc = java.net.URL.new('https://foo.com/abc').openConnection()
print huc.inputStream.to_io.readlines
end
It's a bit screwy that I have to replace a global authenticator to supply credentials for a single host, but this is just a rakefile so I didn't feel too bad about cutting corners in MyAuthenticator.
Here's the equivalent Ruby code:
require 'net/https'
require 'uri'
task :testruby do
https = Net::HTTP.new('foo.com', 443)
https.use_ssl = true
https.ca_file = 'foo.crt'
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
request = Net::HTTP::Get.new('/abc')
request.basic_auth 'userid', 'password'
response = https.request(request)
print response.body
end
Open-uri would have improved the Ruby code dramatically but as far as I can tell open-uri has some hardcoded assumptions about using the machine-wide CA certs. Setting the userid/password per request is nice, but Java wins the certificate handling hands-down. Ruby has a marginal LOC lead for a single request, but Java catches up as soon as you make the second HTTP request.
Chalk up a rare win for Java on this one.