42

I'm using HTTP BASIC Authentication with Java.

My Servlet sends a JMS message but I need to supply the user and password to authenticate myself while creating the connection:

javax.jms.ConnectionFactory.createConnection(String username, String password)

I can retrieve the username from HttpServletRequest.getUserPrincipal(). But there seems to be no way to retrieve the password. How do I solve this?

Jin Kim
  • 16,562
  • 18
  • 60
  • 86

3 Answers3

135

The password you are referring to is most probably different from the one provided by users while login. While the use case is not clear from the question, but it appears you are trying to use the username/password provided by external users to create a connection to JMS Connection Factory. This does not sound architecturally secure to me. You should use only one credential for connecting to ConnectionFactory which needs to be protected( treat it like db connections). Better is to use JNDI to lookup ConnectionFactory and bypass the username/password management stuff.

However, in case you have to use the technique, can use following code block.I am copying it from Gitblit project as it was open in my eclipse

Using Java8 Base64 class:

final String authorization = httpRequest.getHeader("Authorization");
if (authorization != null && authorization.toLowerCase().startsWith("basic")) {
    // Authorization: Basic base64credentials
    String base64Credentials = authorization.substring("Basic".length()).trim();
    byte[] credDecoded = Base64.getDecoder().decode(base64Credentials);
    String credentials = new String(credDecoded, StandardCharsets.UTF_8);
    // credentials = username:password
    final String[] values = credentials.split(":", 2);
}
Thierry
  • 5,270
  • 33
  • 39
Akhilesh Singh
  • 2,548
  • 1
  • 13
  • 10
  • You're right about the architecture. I've since abandoned the approach and just adopted the credentials-free javax.jms.ConnectionFactory.createConnection() approach. – Jin Kim Apr 15 '13 at 15:50
  • 1
    Thanks. It worked but with a tweak. But you cannot call 'Base64' as static class. I did: Base64 b = new Base64(); String credentials = new String(b.decode(base64Credentials), Charset.forName("UTF-8")); – Ankit Singh Jul 08 '14 at 15:22
  • 1
    Note that the Authorization type ("Basic") is case-insensitive, just like all HTTP Header fields. See: https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 So the above code could fail at `.startsWith("Basic") if the headers uses different capitalization – Adriaan Koster Feb 15 '18 at 11:54
  • @AdriaanKoster You're right that it's case-insensitive, but not because it's a header field (it's a header value). It's case-insensitive because [RFC7235](https://tools.ietf.org/html/rfc7235#section-2) says so: `HTTP provides a simple challenge-response authentication framework that can be used by a server to challenge a client request and by a client to provide authentication information. **It uses a case-insensitive token as a means to identify the authentication scheme**, followed by additional information necessary for achieving authentication via that scheme.` (emphasis added) – imgx64 Apr 12 '18 at 05:04
1

The username and password were originally sent in the HTTP Authorization header (base64 encoded) so you could use that; but if the user maintains a session using cookies, they won't necessarily send that header each time.

artbristol
  • 32,010
  • 5
  • 70
  • 103
-1

Those who are looking for the answer even the question is asked long before, here is my solution..

 private void authenticate(HttpServletRequest request){
    String upd=request.getHeader("authorization");
    String pair=new String(Base64.decodeBase64(upd.substring(6)));
    String userName=pair.split(":")[0];
    String password=pair.split(":")[1];    
}

Base64 is imported from - org.apache.commons.codec.binary.Base64;

anjanagnet
  • 51
  • 6