3
votes

I have the context for my Web application defined similar to

<Context>
    <Realm className="org.apache.catalina.realm.JDBCRealm" driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver" connectionURL="jdbc:sqlserver://greensuite.database.windows.net:1433;database=greensuite_db;user=greensuiteapp@greensuite;password=K1B&amp;i9i8*1id^dUzhsv^;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;" userTable="[User]" userNameCol="email" userCredCol="password" userRoleTable="UserGlobalRole" roleNameCol="role">
       <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" encoding="UTF-8" algorithm="SHA-512" iterations="1000000" saltLength="20" />
    </Realm>
</Context>

What can I put in an action listener to be able to do something like:

String passwordHash = credentialHandler.mutate(newPassword);

where credentialHandler is a CredentialHandler instance that applies to the request being processed.

The point is to have the configuration in one place, the context configuration instead of duplicating the configuration in the context configuration and in the code generating and storing a new hash.

1

1 Answers

2
votes

Basically you need to follow the indications given in Christopher Schultz's slides from ApacheCon 2016. Supposing you don't object to referencing Tomcat 8.x catalina.jar in your build process, first import the required classes:

import javax.servlet.ServletContext;
import org.apache.catalina.CredentialHandler;
import org.apache.catalina.Globals;

Then, getting the CredentialHandler is a simple matter of using the correct key to look up the ServletContext's attributes:

public static CredentialHandler getCredentialHandler(final ServletContext context) {
  return (CredentialHandler) context.getAttribute(Globals.CREDENTIAL_HANDLER);
}

The slides give an alternative method using reflection to avoid having to include catalina.jar in your compilation classpath.

Beware though that this only works if you have a single unnested <Realm> configured in your context.xml. If you are wrapping your <Realm> with a LockoutRealm, for instance, the lookup will only consider the outermost Realm returning a generic CredentialHandler, instead of drilling down to the Realm containing the CredentialHandler you configured.