Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing HTTP Basic Authentication in a servlet

I want to write a servlet that wraps around a set of resources and needs to protect them with basic HTTP auth; the submitted username/pass will be checked against the backend database before serving the file.

Does anyone have any working examples of this? I tried the sample at http://www.coderanch.com/t/352345/Servlets/java/HTTP-basic-authentication-Web-Applications but it kept returning an IllegalStateException in the sendError call.

like image 603
Roy Tang Avatar asked Mar 25 '13 09:03

Roy Tang


People also ask

How do I set basic authentication in HTTP?

For HTTP basic authentication, each request must include an authentication header, with a base-64 encoded value. Where siteName is the company name you use to log in to Eloqua, and username and password are your Eloqua username and password.

How do you implement basic authentication?

Basic authentication is easy to define. In the global securityDefinitions section, add an entry with type: basic and an arbitrary name (in this example - basicAuth). Then, apply security to the whole API or specific operations by using the security section.

How is basic authentication implemented in Java?

Basic authentication is a simple authentication method. Clients can authenticate via username and password. These credentials are sent in the Authorization HTTP header in a specific format. It begins with the Basic keyword, followed by a base64-encoded value of username:password.


1 Answers

Here is some code that returns a Credential object (bean object holding login and password).

public Credentials credentialsWithBasicAuthentication(HttpServletRequest req) {
    String authHeader = req.getHeader("Authorization");
    if (authHeader != null) {
        StringTokenizer st = new StringTokenizer(authHeader);
        if (st.hasMoreTokens()) {
            String basic = st.nextToken();

            if (basic.equalsIgnoreCase("Basic")) {
                try {
                    String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8");
                    LOG.debug("Credentials: " + credentials);
                    int p = credentials.indexOf(":");
                    if (p != -1) {
                        String login = credentials.substring(0, p).trim();
                        String password = credentials.substring(p + 1).trim();

                        return new Credentials(login, password);
                    } else {
                        LOG.error("Invalid authentication token");
                    }
                } catch (UnsupportedEncodingException e) {
                    LOG.warn("Couldn't retrieve authentication", e);
                }
            }
        }
    }

    return null;
}

It works well, even with a password as funky as :&=/?é$£.

Here is a basic unit test for the class, using jMock:

public void testCredentialsWithBasicAuthentication() {
    // Setup
    final HttpServletRequest request = context.mock(HttpServletRequest.class);

    AuthentificationHelper helper = new AuthentificationHelper();
    String login = "mickael";
    String password = ":&=/?é$£";
    String base64Hash = Base64.encodeString(login + ":" + password);
    final String authHeader = "Basic " + base64Hash;

    // Expectations
    context.checking(new Expectations() {
        {
            oneOf (request).getHeader("Authorization");
            will(returnValue(authHeader));
        }   
    });

    // Execute
    Credentials credentials = helper.credentialsWithBasicAuthentication(request);

    // Verify
    assertNotNull(credentials);
    assertEquals(login, credentials.getLogin());
    assertEquals(password, credentials.getPassword());

    context.assertIsSatisfied();
}
like image 158
Dirty Henry Avatar answered Oct 16 '22 19:10

Dirty Henry