Skip to content

Instantly share code, notes, and snippets.

@jeanouii
Created March 20, 2014 15:44
Show Gist options
  • Select an option

  • Save jeanouii/9666739 to your computer and use it in GitHub Desktop.

Select an option

Save jeanouii/9666739 to your computer and use it in GitHub Desktop.
/**
* <p>This LoginModule aims at using the default tomcat-users.xml file for authenticating and provisioning roles to a
* user.</p>
* <p/>
* <p>This login module is indented to be wrapped by the CDILoginModule provided by TomEE. So that it's possible to
* get the Tomcat UserDatabase using a common injection.</p>
* <p/>
* <p>Configuration in Tomcat/TomEE</p>
* <ul>
* <li>Add the UserDatabase resource (or check it's already defined.</li>
* <pre>
* &lt;!-- Global JNDI resources
* Documentation at /docs/jndi-resources-howto.html
* --&gt;
* &lt;GlobalNamingResources&gt;
* &lt;!-- Editable user database that can also be used by
* UserDatabaseRealm to authenticate users
* --&gt;
* &lt;Resource name="UserDatabase" auth="Container"
* type="org.apache.catalina.UserDatabase"
* description="User database that can be updated and saved"
* factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
* pathname="conf/tomcat-users.xml" /&gt;
* &lt;/GlobalNamingResources&gt;
* </pre>
*
* <li>Configure the JAASRealm in Tomcat/TomEE</li>
* <pre>
* &lt;Realm className="org.apache.catalina.realm.JAASRealm"
* appName="applicationNameInJaasConfig"
* userClassNames="org.apache.openejb.core.security.jaas.UserPrincipal"
* roleClassNames="org.apache.openejb.core.security.jaas.GroupPrincipal"/&gt;
* </pre>
*
* <li>Configure JAAS LoginModule in <code>jaas.config</code>. <strong>This module must be wrapped into the
* TomEE provided CDILoginModule to have CDI features.</strong></li>
* <pre>
* applicationNameInJaasConfig {
* org.apache.openejb.core.security.jaas.CDILoginModule required
* delegate="com.tomitribe.security.jaas.TomcatUsersLoginModule"
* loginModuleAsCdiBean=true;
};
* </pre>
* </ul>
*/
public class TomcatUsersLoginModule implements LoginModule {
private static Logger LOGGER = Logger.getLogger(TomcatUsersLoginModule.class.getName());
@Resource
private UserDatabase userDatabase;
private Subject subject;
private CallbackHandler callbackHandler;
private Map<String, Object> sharedState;
private Map<String, ?> options;
private boolean debug;
private String username;
private User user;
private Set principals = new LinkedHashSet();
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
Map<String, ?> options) {
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = (Map<String, Object>) sharedState;
this.options = options;
debug = "true".equalsIgnoreCase((String) options.get("debug"));
}
@Override
public boolean login() throws LoginException {
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("Username: ");
callbacks[1] = new PasswordCallback("Password: ", false);
try {
callbackHandler.handle(callbacks);
} catch (IOException ioe) {
throw new LoginException(ioe.getMessage());
} catch (UnsupportedCallbackException uce) {
throw new LoginException(uce.getMessage() + " not available to obtain information from user");
}
username = ((NameCallback) callbacks[0]).getName();
char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
if (tmpPassword == null) tmpPassword = new char[0];
user = userDatabase.findUser(username);
if (user == null) throw new FailedLoginException("User does not exist");
String password = user.getPassword();
if (!password.equals(new String(tmpPassword))) throw new FailedLoginException("Password does not match");
if (debug) {
LOGGER.fine("Logged in as '" + user + "'");
}
return true;
}
@Override
public boolean commit() throws LoginException {
principals.add(new UserPrincipal(username));
Iterator<Role> uRoles = user.getRoles();
while (uRoles.hasNext()) {
Role role = uRoles.next();
principals.add(new GroupPrincipal(role.getName()));
}
Iterator<Group> uGroups = user.getGroups();
while (uGroups.hasNext()) {
Group group = uGroups.next();
uRoles = group.getRoles();
while (uRoles.hasNext()) {
Role role = uRoles.next();
principals.add(new GroupPrincipal(role.getName()));
}
}
subject.getPrincipals().addAll(principals);
if (debug) {
LOGGER.fine("Commit for user '" + user + "'");
}
return true;
}
@Override
public boolean abort() throws LoginException {
clear();
if (debug) {
LOGGER.fine("Abort");
}
return true;
}
private void clear() {
principals.clear();
user = null;
username = null;
}
@Override
public boolean logout() throws LoginException {
clear();
if (debug) {
LOGGER.fine("Logged out for user'" + user + "'");
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment