Question

I have a requirement to perform HTTP authentication logic within a servlet application, rather than delegating this task to the container.

Specifically, I need a way of taking the headers of an HttpServletRequest which contains HTTP auth headers, and having them decoded into a data structure representing the supplied credentials, which the application can then process. Both basic and digest auth should be supported.

I could write this by hand, it wouldn't be too much of a chore, the RFCs are all well documented, but I'd quite like to use an off-the shelf library to do it for me.

My first thought was Spring Security, but from what I can tell this delegates this task to the container (I'm a bit unclear on that, it's a complicated code base).

Anyone know of any others?

Was it helpful?

Solution

  • For BASIC, it is very easy to implement - just read the header, base64 decode it and split it on the ':' character. You can also use use Spring's BasicProcessingFilter, and supply your instance of AuthenticationManager.
  • With Digest, you cannot get the password from the request (that's the whole point...). Implementing all the details is not a trivial task, even thought the protocol is well documented. Therefore I'd go with Spring's DigestProcessingFilter. In this case you need to supply the UserDetailsService who provides the user's password based on the username (for the digest).

OTHER TIPS

Here is my decoder:

public static String[] decodeBasicAuth(String authorization) {
    if (authorization == null)
        throw new RuntimeException("Invalid Authorization String.");
    if (authorization.length() < 9)
        throw new RuntimeException("Invalid Authorization String.");
    if (authorization.length() > 64)
        throw new RuntimeException("Invalid Authorization String.");
    String s[] = authorization.split("\\s", 3);
    if (s.length < 2)
        throw new RuntimeException("Invalid Authorization String.");
    for (int i = 0; i < s.length; i++) {
        String part = s[i];
        if (part.compareTo("Basic") == 0) {
            String userPassBase64 = s[i + 1];
            if (!userPassBase64.isEmpty()) {
                String userPass = null;
                try {
                    userPass = new String(DatatypeConverter.parseBase64Binary(userPassBase64));
                } catch (RuntimeException e) {
                    throw new RuntimeException("Authorization cannot be decoded.", e);
                }
                String userPassArray[] = userPass.split(":");
                if (userPassArray.length == 2) {
                    return userPassArray;
                } else {
                    throw new RuntimeException("Invalid Authorization String.");
                }
            } else {
                throw new RuntimeException("Invalid Authorization String.");
            }
        }
    }
    throw new RuntimeException("Authorization cannot be decoded.");
}

I don't know of a framework off hand, but unless you're using BASIC authentication, you might not be able to get the password for the user.

If you are using BASIC authentication, it's pretty trivial to Base64Decode the Authentication header.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top