The UrBlog

John's Ramblings about Software Development

Implementing REST Authentication

While there is not much written about REST authentication, there does seem to be a common theme among the few articles written about it that REST services should be authenticated by signing the query parameters using a private key and making the calls over HTTPS. This posting will provide an example of the signing of query parameters using a simple Spring server. We’ll provide a small twist by putting the authentication information in headers.

more…

Hosting a Maven Internal Repository on a File Share

I spent some time today setting up an internal repository for my Maven build. I wanted to host just the artifacts that are used by my projects and not allow the project build to go outside of that repository. I first setup my repositories like this:

<repositoriesa>
  <repository>
    <id>central</id>
    <name>My Company's Internal Repository</name>
    <url>file:///server/Maven/repo/</url>
  </repository>
</repositories>

The idea behind this setup is that I overrode the “central” repository and pointed it to my internal repository. This way Maven would not try to go out to repo1.maven.org if it did not find something.

And it did not work. After much research and trying many things, it turns out my URL needs to look like this:

<url>file://\\server\Maven\repo\</url>

Hope this helps someone in the future trying to setup a repository on a share.

Using a HostnameVerifier With Spring Web Services

I was working with a web service from a site that uses SSL with a certificate that was self-signed. When attempting to make the calls, I received the error:

    javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching {web address} found

The workaround for this issue is to provide a HostnameVerifer that skips the host name verification process. There is an example of how to do this here.

I ran into this issue after I had a nice clean codebase using Spring’s WebServiceTemplate and RestTemplate. It took some digging, but I was able to find the spots where I had to install the verifier. We start with a NullHostnameVerifier that returns true for everything:

public class NullHostnameVerifier implements HostnameVerifier {
   public boolean verify(String hostname, SSLSession session) {
      return true;
   }
}

The org.springframework.ws.client.core.WebServiceTempate extends org.springframework.ws.client.support.WebServiceAccesor which uses a org.springframework.ws.client.support.WebServiceMessageSender. The WebServiceMessage sender for HTTPS is org.springframework.ws.transport.http.HttpsUrlConnectionMessageSender which is found in the spring-ws-support-1.5.9.jar. We need to create one of these and set the HostnameVerifier into it and pass it along to the WebServicesTemplate:

public void setWebServicesTempalate(WebServicesTemplate template) {
   HostnameVerifier verifier = new NullHostnameVerifier();
   HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender();
   sender.setHostnameVerifier(verifier);
   template.setMessageSender(sender);
   this.template = template;
}

The org.springframework.web.client.RestTemplate is setup differently. It uses a org.springframework.http.client.ClientHttpRequestFactory to handle the connections. Stepping thru the code, I found the RestTemplate using org.springframework.http.client.SimpleClientHttpRequestFactory which has a protected prepareConnection(…) method I could override and catch the HttpsURLConnection which I could set the verifier in. First we need our own ClientHttpRequestFactory:

 
public class MySimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory {

   private final HostnameVerifier verifier;

   public MySimpleClientHttpRequestFactory(HostnameVerifier verifier) {
      this.verifier = verifier;
   }

   @Override
   protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
      if (connection instanceof HttpsURLConnection) {
         ((HttpsURLConnection) connection).setHostnameVerifier(verifier);
      }
      super.prepareConnection(connection, httpMethod);
   }

}

Now we can use that as the request factory in our RestTemplate:

public void setRestTemplate(RestTemplate template) {
   HostnameVerifier verifier = new NullHostnameVerifier();
   MySimpleClientHttpRequestFactory factory = new MySimpleClientHttpRequestFactory(verifier);
   template.setRequestFactory(factory);
   this.template = template;
}

Once the NullHostnameVerifer is in place in the WebServiceTemplate and the RestTemplate, we will no longer see the error

Transmitting Unicode Data Between C++ and Java

We ran into an issue this week were we had to figure out how to transmit Unicode data between a C++ program and a Java program using TCP. We have a working program that is sending ASCII just fine. We expected the C++ Unicode work would be difficult and the Java work would be easy. It turns out the C++ side was not as difficult as we thought. The Java side turned out to be easy, but it took some time to figure out how to make it work. Here’s a quick explanation of what we found:

C++

Most of our C++ code is using the standard library (i.e. std::string) and boost::asio for the networking. After a bit if research, I created a tstring.hpp file using code I found here and here. I changed the networking code to use the new std::tstring instead of std::string and was able to deal with Unicode data. Here’s an example of the asio code to read data sent from Java. Java sends a header with “file0000000000” where the 10 digits contain the data length, followed by the data itself. Notice the buffer size is the size * sizeof(TCHAR) to account for the fact that wide char are twice the size of normal char.

class session : public boost::enable_shared_from_this<session>
{
public:
  void read_header()
  {
    buffer_.resize(14);
    boost::asio::async_read(
      socket_,
      boost::asio::buffer(buffer_, buffer_.size() * sizeof(TCHAR)),
      boost::bind(
    &session::handle_read_header, 
    shared_from_this(),
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred));
  }

  void handle_read_header(const boost::system::error_code& error, size_t bytes_transferred)
  {
    if (error) return;

    std::tstring data(buffer_.begin(), buffer_.end());
    short length = boost::lexical_cast<short>(data.substr(4));

    buffer_.resize(length);
    boost::asio::async_read(
      socket_,
      boost::asio::buffer(buffer_, buffer_.size() * sizeof(TCHAR)),
      boost::bind(
    &session::handle_read_data, 
    shared_from_this(),
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred));
  }

  void handle_read_data(const boost::system::error_code& error, size_t bytes_transferred)
  {
    if (error && error.value() != 2) return;
    std::tstring data(buffer_.begin(), buffer_.end());
    // process data
    read_header();
  }

private:
  tcp::socket socket_;
  std::vector<TCHAR> buffer_;
  int count_;

};

Java

For an example, we created a simple Java program that would load in a Unicode file, append a header and send it to the C++ code above. What took a great deal of time was figuring out how to get the data in the correct format. It turns out the way the C++ program was looking for data was in UTF-16LE format. We took our data string and called getBytes(“UTF-16LE”) to get the data in the correct format to send.

String data = getFileContents();
Formatter f = new Formatter();
String header = f.format("file%010d", data.length() * 2).toString(); 
data = header + data;
byte[] buffer = data.getBytes("UTF-16LE");
Socket socket = new Socket(address, port);
BufferedOutputStream bis = new BufferedOutputStream(socket.getOutputStream());
try {
   bis.write(buffer);
   bis.flush();
} finally {
   bis.close();
}

In the end, this turns out to be easy to do. It just takes a bit of time to figure out the settings. We had to spend time searching for bits and pieces of info to put this together. If you happen to know any good resources to help others with this, feel free to add a comment.