33

I'm writing a Java client that POSTs to a HTTP server that requires authentication.
I have to support at least the following three authentication methods: Basic, Digest or Negotiate. Additionally the POST may be very large (over 2MB), so I need to use streaming. As is documented for HttpURLConnection

When output streaming is enabled, authentication and redirection cannot be handled automatically. A HttpRetryException will be thrown when reading the response if authentication or redirection are required.

So, I need to handle authentication myself. I searched, and searched again, for a way to employ the, already coded, classes - but found no way...

I could just pluck the needed sources from here (as they are GPLv2 with Classpath exception). Is this the right way?

Thanks.

Bruno De Fraine
  • 45,466
  • 8
  • 54
  • 65
Opher
  • 525
  • 1
  • 4
  • 11

2 Answers2

49

Do you need output streaming? The HttpURLConnection most definitely supports authentication with the Authenticator class, see: Http Authentication.

Update: In case the Authenticator is not an option, you can manually do HTTP basic authentication by adding an extra header to your HTTP request. Try the following code (untested):

String userPassword = username + ":" + password;
String encoding = new sun.misc.BASE64Encoder().encode(userPassword.getBytes());
URLConnection uc = url.openConnection();
uc.setRequestProperty("Authorization", "Basic " + encoding);
uc.connect();
Denilson Sá Maia
  • 47,466
  • 33
  • 109
  • 111
Bruno De Fraine
  • 45,466
  • 8
  • 54
  • 65
  • Yes. My **POST** includes a file which may well be over 2MB in size. – Opher Feb 03 '11 at 12:02
  • Thanks. I updated my question to clarify that I need to handle either Basic, Digest or Negotiate authentication. What I really need help with is _Negotiate_ – Opher Feb 04 '11 at 10:06
  • 3
    sun.misc.BASE64Encoder is JVM dependant. A better option would probably be using org.apache.commons.codec.binary.Base64 from Apache. – Mat Jul 19 '13 at 14:28
  • 6
    Related to @Mat's comment: on Android, you'll want to use `Base64.encodeToString()` ([code example](http://stackoverflow.com/a/7360440/56285)). – Jonik Apr 02 '14 at 09:00
  • 1
    What is the process with Https will this also work ? – DevilCode Apr 19 '16 at 16:19
  • 1
    I have error: java.lang.IllegalArgumentException: Illegal character(s) in message header value: Basic YTFkOWY2ZjkzMzE2NDA2OTljYzA3ZjJkYzkyYTQ0Yjk6azF3bjFFelJ1RkdPeGdicnVtTk83b0Ft0pjVW1BV0ljVTFmK2pNbmpLcz0= at sun.net.www.protocol.http.HttpURLConnection.checkMessageHeader(HttpURLConnection.java:482) at sun.net.www.protocol.http.HttpURLConnection.isExternalMessageHeaderAllowed(HttpURLConnection.java:434) at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:2753) Why? – Koss Aug 10 '17 at 05:32
4

Related to @Mat's comment :

Here is an example used by my team and I :

import org.apache.commons.codec.binary.Base64;

HttpGet getRequest = new HttpGet(endpoint);
getRequest.addHeader("Authorization", "Basic " + getBasicAuthenticationEncoding());

private String getBasicAuthenticationEncoding() {

        String userPassword = username + ":" + password;
        return new String(Base64.encodeBase64(userPassword.getBytes()));
    }

Hope it helps!

lboix
  • 969
  • 12
  • 14
  • My Eclipse didn't find the codec package, but you can directly download it from http://commons.apache.org/proper/commons-codec/download_codec.cgi and add the jar as reference! – Tyron Feb 05 '16 at 08:43