Httpurlconnection java basic authentication

How to send an HTTP request to a HTTP Basic Authentication endpoint in Java without using any external libraries

One common task for Java developers is to write codes that communicate with API endpoints. Chances are these endpoints could use HTTP Basic Authentication for authenticating the HTTP request sender.

Although there are good libraries to help us craft and send HTTP requests to a web server in Java, I prefer to use the Java core library so as to keep my Java program lightweight.

Referencing my earlier post on how to construct a HTTP request to an endpoint with HTTP basic authentication, this post documents how to send an HTTP request to a HTTP Basic Authentication endpoint in Java without using any external libraries.

Using httpbin.org to test our HTTP request with HTTP Basic Authentication

For the sake of brevity, we will use an endpoint from httpbin.org to test out the Java codes that we are going to write.

This endpoint is available at http://httpbin.org/basic-auth/user/passwd. It expects a HTTP Basic Authentication request with:

  • HTTP GET as the HTTP method,
  • user as the username
  • and passwd as the password
Читайте также:  Консольный ввод данных java

Java codes for generating a Base64 encoded String payload from a username and password pair

The first step in crafting a HTTP request for a HTTP Basic Authentication endpoint is to generate a Base64 encoded String payload from the username and password. Lucky for us, Java 8 provided java.util.Base64 to help us with Base64 encoding.

The following Java 8 codes generate a Base64 encoded String payload with user as the username and passwd as the password:

String usernameColonPassword = "user:passwd"; String basicAuthPayload = "Basic " + Base64.getEncoder().encodeToString(usernameColonPassword.getBytes());

To generate the HTTP Basic Authentication payload, we simply:

  1. concatenate the username, a colon and the password,
  2. pass the concatenated String as bytes to Base64.getEncoder().encodeToString to get a Base64 encoded String,
  3. and prepend the Base64 encode String with the String «Basic «.

Java codes for sending HTTP request to the HTTP Basic Authentication endpoint

With the basicAuthPayload , we can then proceed with crafting and sending the HTTP request to the HTTP Basic Authentication endpoint.

To avoid external libraries, we can use the following classes that are provided by the Java code library for sending the HTTP request:

  • java.io.BufferedReader
  • java.io.BufferedWriter
  • java.io.File
  • java.io.FileInputStream
  • java.io.InputStreamReader
  • java.io.OutputStream
  • java.io.OutputStreamWriter
  • java.net.HttpURLConnection
  • java.net.URL

And write the following codes to send a HTTP GET request to a HTTP Basic Authentication endpoint:

BufferedReader httpResponseReader = null; try < // Connect to the web server endpoint URL serverUrl = new URL("http://httpbin.org/basic-auth/user/passwd"); HttpURLConnection urlConnection = (HttpURLConnection) serverUrl.openConnection(); // Set HTTP method as GET urlConnection.setRequestMethod("GET"); // Include the HTTP Basic Authentication payload urlConnection.addRequestProperty("Authorization", basicAuthPayload); // Read response from web server, which will trigger HTTP Basic Authentication request to be sent. httpResponseReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); String lineRead; while((lineRead = httpResponseReader.readLine()) != null) < System.out.println(lineRead); >> catch (IOException ioe) < ioe.printStackTrace(); >finally < if (httpResponseReader != null) < try < httpResponseReader.close(); >catch (IOException ioe) < // Close quietly >> >

Putting it together

The following is a Java main class that contains all the codes that we had discussed:

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Base64; public class HttpBasicAuthenticationExample < public static void main(String[] args) < String usernameColonPassword = "user:passwd"; String basicAuthPayload = "Basic " + Base64.getEncoder().encodeToString(usernameColonPassword.getBytes()); BufferedReader httpResponseReader = null; try < // Connect to the web server endpoint URL serverUrl = new URL("http://httpbin.org/basic-auth/user/passwd"); HttpURLConnection urlConnection = (HttpURLConnection) serverUrl.openConnection(); // Set HTTP method as GET urlConnection.setRequestMethod("GET"); // Include the HTTP Basic Authentication payload urlConnection.addRequestProperty("Authorization", basicAuthPayload); // Read response from web server, which will trigger HTTP Basic Authentication request to be sent. httpResponseReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); String lineRead; while((lineRead = httpResponseReader.readLine()) != null) < System.out.println(lineRead); >> catch (IOException ioe) < ioe.printStackTrace(); >finally < if (httpResponseReader != null) < try < httpResponseReader.close(); >catch (IOException ioe) < // Close quietly >> > > >

Running the above code will produce the following output:

You may wish to change the String literal that is assigned to the usernameColonPassword variable and observe what happens.

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people. All views expressed belongs to him and are not representative of the company that he works/worked for.

Источник

Java NET — Basic Authentication with URLConnection

HTTP Basic authentication is the technique for enforcing access controls to web resources. The clients who want to access the protected resources, should send Authorization request header with an encoded (Base64) user/password value:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

If above authentication fails, the server will respond back with WWW-Authenticate response header and the status code 401 (Unauthorized):

WWW-Authenticate: Basic realm="Some value"

java.net.URLConnection provides suitable API to send ‘Authorization’ request header. Let’s see an example how to do that.

The Server

In this example, we are going to write a very simple Java Servlet. We will also use Tomcat server (embedded), which provides container managed authorization/authentication.

Servlet

package com.logicbig.example; import javax.servlet.ServletException; import javax.servlet.annotation.HttpConstraint; import javax.servlet.annotation.HttpMethodConstraint; import javax.servlet.annotation.ServletSecurity; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet(name = "appController", urlPatterns = ) @ServletSecurity( value = @HttpConstraint(rolesAllowed = ), httpMethodConstraints = < @HttpMethodConstraint(value = "GET", rolesAllowed = ) >) public class MyServlet extends HttpServlet < @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < PrintWriter writer = resp.getWriter(); writer.println("User authorized prettyprint b-c-s">  BASIC employee-realm  

src/main/webapp/config/tomcat-users.xml

To try examples, run embedded tomcat (configured in pom.xml of example project below):

URLConnection client

First, we will try to access the resource without ‘Authorization’ header:

package com.logicbig.example; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.List; import java.util.Map; public class URLConnectionClient < public static void main(String[] args) throws Exception < URL myURL = new URL("http://localhost:8080"); URLConnection c = myURL.openConnection(); Map> headers = c.getHeaderFields(); System.out.println("-- Response headers --"); headers.entrySet() .forEach(e -> System.out.printf("%s: %s%n", e.getKey(), e.getValue())); System.out.println("-- Response body --"); try (BufferedReader reader = new BufferedReader( new InputStreamReader(c.getInputStream()))) < reader.lines().forEach(System.out::println); >> >

Output

-- Response headers --
null: [HTTP/1.1 401 Unauthorized]
Cache-Control: [private]
Server: [Apache-Coyote/1.1]
WWW-Authenticate: [Basic realm="employee-realm"]
Expires: [Wed, 31 Dec 1969 18:00:00 CST]
Content-Length: [951]
Date: [Thu, 08 Jun 2017 03:07:55 GMT]
Content-Language: [en]
Content-Type: [text/html;charset=utf-8]
-- Response body --
Exception in thread "main" java.io.IOException: Server returned HTTP response code: 401 for URL: http://localhost:8080
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1890)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1885)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1884)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1457)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at com.logicbig.example.URLConnectionClient.main(URLConnectionClient.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.io.IOException: Server returned HTTP response code: 401 for URL: http://localhost:8080
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1840)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at sun.net.www.protocol.http.HttpURLConnection.getHeaderFields(HttpURLConnection.java:2966)
at com.logicbig.example.URLConnectionClient.main(URLConnectionClient.java:14)
. 5 more

Let’s set ‘Authorization’ header with appropriate values:

package com.logicbig.example; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; import java.util.Base64; import java.util.List; import java.util.Map; public class URLConnectionClient2 < public static void main(String[] args) throws Exception < URL myURL = new URL("http://localhost:8080"); URLConnection c = myURL.openConnection(); String authStr = Base64.getEncoder() .encodeToString("Tom:abc".getBytes()); //setting Authorization header c.setRequestProperty("Authorization", "Basic " + authStr); Map> headers = c.getHeaderFields(); System.out.println("-- Response headers --"); headers.entrySet() .forEach(e -> System.out.printf("%s: %s%n", e.getKey(), e.getValue())); System.out.println("-- Response body --"); try (BufferedReader reader = new BufferedReader( new InputStreamReader(c.getInputStream()))) < reader.lines().forEach(System.out::println); >> >

Output

-- Response headers --
null: [HTTP/1.1 200 OK]
Cache-Control: [private]
Server: [Apache-Coyote/1.1]
Expires: [Wed, 31 Dec 1969 18:00:00 CST]
Content-Length: [51]
Date: [Thu, 08 Jun 2017 03:07:34 GMT]
-- Response body --
User authorized= GenericPrincipal[Tom(employee,)]

Example Project

Dependencies and Technologies Used:

Источник

java-http-url-connection

In this tutorial, we’re going to explore how to authenticate HTTP requests using the HttpUrlConnection class.

2. HTTP Authentication

In web applications, servers may require clients to authenticate themselves. Failing to comply usually results in the server returning an HTTP 401 (Unauthorized) status code.

There are multiple authentication schemes that differ in the security strength they provide. However, the implementation effort varies as well.

  • basic is a scheme which we’ll say more about in the next section
  • digest applies hash algorithms on user credentials and a server-specified nonce
  • bearer utilizes access tokens as part of OAuth 2.0

3. Basic Authentication

Basic authentication allows clients to authenticate themselves using an encoded user name and password via the Authorization header:

GET / HTTP/1.1 Authorization: Basic dXNlcjpwYXNzd29yZA==

To create the encoded user name and password string, we simply Base64-encode the username, followed by a colon, followed by the password:

basic(user, pass) = base64-encode(user + ":" + pass)

Remember some caution from RFC 7617, though:

This scheme is not considered to be a secure method of user authentication unless used in conjunction with some external secure system such as TLS

This is, of course, since the user name and password travel as plain text over the network within each request.

4. Authenticate a Connection

Okay, with that as background, let’s jump into configuring HttpUrlConnection to use HTTP Basic.

The class HttpUrlConnection can send requests, but first, we have to obtain an instance of it from an URL object:

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

A connection offers many methods to configure it, like setRequestMethod and setRequestProperty.

As odd as setRequestProperty sounds, this is the one we want.

Once we’ve joined the user name and password using “:”, we can use the java.util.Base64 class to encode the credentials:

String auth = user + ":" + password; byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.UTF_8));

Then, we create the header value from the literal “Basic ” followed by the encoded credentials:

String authHeaderValue = "Basic " + new String(encodedAuth);

Next, we call the method setRequestProperty(key, value) to authenticate the request. As mentioned previously, we have to use “Authorization” as our header and “Basic ” + encoded credentials as our value:

connection.setRequestProperty("Authorization", authHeaderValue);

Finally, we need to actually send the HTTP request, like for example by calling getResponseCode(). As a result, we get an HTTP response code from the server:

int responseCode = connection.getResponseCode();

Anything in the 2xx family means that our request including the authentication part was okay!

5. Java Authenticator

The above-mentioned basic auth implementation requires setting the authorization header for every request. In contrast, the abstract class java.net.Authenticator allows setting the authentication globally for all connections.

We need to extend the class first. Then, we call the static method Authenticator.setDefault() in order to register an instance of our authenticator:

Authenticator.setDefault(new BasicAuthenticator());

Our basic auth class just overrides the getPasswordAuthentication() non-abstract method of the base class:

private final class BasicAuthenticator extends Authenticator < protected PasswordAuthentication getPasswordAuthentication() < return new PasswordAuthentication(user, password.toCharArray()); >>

The Authenticator class utilizes the credentials of our authenticator to fulfill the authentication scheme required by the server automatically.

6. Conclusion

In this short tutorial, we’ve seen how to apply basic authentication to requests sent via HttpUrlConnection.

As always, the code example can be found on GitHub.

Источник

Оцените статью