diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java index 1a2e141bca7..6fd2660e6b6 100644 --- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java +++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractDatabaseLoginModule.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.jaas.spi; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -59,6 +58,24 @@ public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule * @throws Exception if unable to get the connection */ public abstract Connection getConnection () throws Exception; + + + public class JDBCUserInfo extends UserInfo + { + public JDBCUserInfo (String userName, Credential credential) + { + super(userName, credential); + } + + + + @Override + public List doFetchRoles () + throws Exception + { + return getRoles(getUserName()); + } + } @@ -92,8 +109,22 @@ public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule return null; } + + + return new JDBCUserInfo (userName, Credential.getCredential(dbCredential)); + } + } + + + public List getRoles (String userName) + throws Exception + { + List roles = new ArrayList(); + + try (Connection connection = getConnection()) + { //query for role names - List roles = new ArrayList(); + try (PreparedStatement statement = connection.prepareStatement (rolesQuery)) { statement.setString (1, userName); @@ -106,10 +137,13 @@ public abstract class AbstractDatabaseLoginModule extends AbstractLoginModule } } } - - return new UserInfo (userName, Credential.getCredential(dbCredential), roles); + } + + return roles; } + + public void initialize(Subject subject, diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java index 67b2f5484b5..0bcdd54c171 100644 --- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java +++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/AbstractLoginModule.java @@ -54,6 +54,12 @@ public abstract class AbstractLoginModule implements LoginModule private JAASUserInfo currentUser; private Subject subject; + /** + * JAASUserInfo + * + * This class unites the UserInfo data with jaas concepts + * such as Subject and Principals + */ public class JAASUserInfo { private UserInfo user; @@ -62,7 +68,8 @@ public abstract class AbstractLoginModule implements LoginModule public JAASUserInfo (UserInfo u) { - setUserInfo(u); + this.user = u; + this.principal = new JAASPrincipal(u.getUserName()); } public String getUserName () @@ -75,19 +82,7 @@ public abstract class AbstractLoginModule implements LoginModule return this.principal; } - public void setUserInfo (UserInfo u) - { - this.user = u; - this.principal = new JAASPrincipal(u.getUserName()); - this.roles = new ArrayList(); - if (u.getRoleNames() != null) - { - Iterator itor = u.getRoleNames().iterator(); - while (itor.hasNext()) - this.roles.add(new JAASRole((String)itor.next())); - } - } - + public void setJAASInfo (Subject subject) { subject.getPrincipals().add(this.principal); @@ -106,6 +101,18 @@ public abstract class AbstractLoginModule implements LoginModule { return this.user.checkCredential(suppliedCredential); } + + public void fetchRoles() throws Exception + { + this.user.fetchRoles(); + this.roles = new ArrayList(); + if (this.user.getRoleNames() != null) + { + Iterator itor = this.user.getRoleNames().iterator(); + while (itor.hasNext()) + this.roles.add(new JAASRole((String)itor.next())); + } + } } public Subject getSubject () @@ -174,7 +181,6 @@ public abstract class AbstractLoginModule implements LoginModule */ public boolean commit() throws LoginException { - if (!isAuthenticated()) { currentUser = null; @@ -252,7 +258,10 @@ public abstract class AbstractLoginModule implements LoginModule setAuthenticated(currentUser.checkCredential(webCredential)); if (isAuthenticated()) + { + currentUser.fetchRoles(); return true; + } else throw new FailedLoginException(); } diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java index c66ff431fd1..73ccb914dd9 100644 --- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java +++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/LdapLoginModule.java @@ -176,6 +176,28 @@ public class LdapLoginModule extends AbstractLoginModule private DirContext _rootContext; + + public class LDAPUserInfo extends UserInfo + { + + /** + * @param userName + * @param credential + */ + public LDAPUserInfo(String userName, Credential credential) + { + super(userName, credential); + } + + @Override + public List doFetchRoles() throws Exception + { + return getUserRoles(_rootContext, getUserName()); + } + + } + + /** * get the available information about the user *

@@ -199,9 +221,7 @@ public class LdapLoginModule extends AbstractLoginModule pwdCredential = convertCredentialLdapToJetty(pwdCredential); Credential credential = Credential.getCredential(pwdCredential); - List roles = getUserRoles(_rootContext, username); - - return new UserInfo(username, credential, roles); + return new LDAPUserInfo(username, credential); } protected String doRFC2254Encoding(String inputString) @@ -411,12 +431,17 @@ public class LdapLoginModule extends AbstractLoginModule setCurrentUser(new JAASUserInfo(userInfo)); + boolean authed = false; if (webCredential instanceof String) - { - return credentialLogin(Credential.getCredential((String) webCredential)); - } - - return credentialLogin(webCredential); + authed = credentialLogin(Credential.getCredential((String) webCredential)); + else + authed = credentialLogin(webCredential); + + //only fetch roles if authenticated + if (authed) + getCurrentUser().fetchRoles(); + + return authed; } catch (UnsupportedCallbackException e) { @@ -496,16 +521,18 @@ public class LdapLoginModule extends AbstractLoginModule String filter = "(&(objectClass={0})({1}={2}))"; - LOG.info("Searching for users with filter: \'" + filter + "\'" + " from base dn: " + _userBaseDn); + if (LOG.isDebugEnabled()) + LOG.debug("Searching for users with filter: \'" + filter + "\'" + " from base dn: " + _userBaseDn); Object[] filterArguments = new Object[]{ - _userObjectClass, - _userIdAttribute, - username + _userObjectClass, + _userIdAttribute, + username }; NamingEnumeration results = _rootContext.search(_userBaseDn, filter, filterArguments, ctls); - LOG.info("Found user?: " + results.hasMoreElements()); + if (LOG.isDebugEnabled()) + LOG.debug("Found user?: " + results.hasMoreElements()); if (!results.hasMoreElements()) { diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java index 097d9431214..3560f2b57bd 100644 --- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java +++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/PropertyFileLoginModule.java @@ -101,7 +101,7 @@ public class PropertyFileLoginModule extends AbstractLoginModule } /** - * Don't implement this as we want to pre-fetch all of the users. + * * * @param userName the user name * @throws Exception if unable to get the user information @@ -117,6 +117,8 @@ public class PropertyFileLoginModule extends AbstractLoginModule if (userIdentity==null) return null; + //TODO in future versions change the impl of PropertyUserStore so its not + //storing Subjects etc, just UserInfo Set principals = userIdentity.getSubject().getPrincipals(); List roles = new ArrayList(); diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/UserInfo.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/UserInfo.java index c15e3ba185a..c13061d1af7 100644 --- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/UserInfo.java +++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/spi/UserInfo.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.jaas.spi; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.eclipse.jetty.util.security.Credential; @@ -29,24 +30,70 @@ import org.eclipse.jetty.util.security.Credential; * This is the information read from the external source * about a user. * - * Can be cached by a UserInfoCache implementation + * Can be cached. */ public class UserInfo { private String _userName; private Credential _credential; - private List _roleNames; + protected List _roleNames = new ArrayList<>(); + protected boolean _rolesLoaded = false; + /** + * @param userName + * @param credential + * @param roleNames + */ public UserInfo (String userName, Credential credential, List roleNames) { _userName = userName; _credential = credential; - _roleNames = new ArrayList(); if (roleNames != null) { - _roleNames.addAll(roleNames); + synchronized (_roleNames) + { + _roleNames.addAll(roleNames); + _rolesLoaded = true; + } + } + } + + + /** + * @param userName + * @param credential + */ + public UserInfo (String userName, Credential credential) + { + this (userName, credential, null); + } + + + + /** + * Should be overridden by subclasses to obtain + * role info + * + * @return + * @throws Exception + */ + public List doFetchRoles () + throws Exception + { + return Collections.emptyList(); + } + + public void fetchRoles () throws Exception + { + synchronized (_roleNames) + { + if (!_rolesLoaded) + { + _roleNames.addAll(doFetchRoles()); + _rolesLoaded = true; + } } } @@ -56,8 +103,8 @@ public class UserInfo } public List getRoleNames () - { - return new ArrayList(_roleNames); + { + return Collections.unmodifiableList(_roleNames); } public boolean checkCredential (Object suppliedCredential) diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java index 141597d4f2a..aa61b57a0e9 100644 --- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java @@ -73,6 +73,33 @@ public class DataSourceLoginService extends MappedLoginService private String _userSql; private String _roleSql; private boolean _createTables = false; + + + /** + * DBUser + * + * + */ + public class DBUser extends KnownUser + { + private int _key; + + /** + * @param name + * @param credential + */ + public DBUser(String name, Credential credential, int key) + { + super(name, credential); + _key = key; + } + + public int getKey () + { + return _key; + } + + } /* ------------------------------------------------------------ */ public DataSourceLoginService() @@ -290,13 +317,13 @@ public class DataSourceLoginService extends MappedLoginService * * @param userName the user name */ - @Override + @Deprecated protected UserIdentity loadUser (String userName) { try { try (Connection connection = getConnection(); - PreparedStatement statement1 = connection.prepareStatement(_userSql)) + PreparedStatement statement1 = connection.prepareStatement(_userSql)) { statement1.setObject(1, userName); try (ResultSet rs1 = statement1.executeQuery()) @@ -305,19 +332,20 @@ public class DataSourceLoginService extends MappedLoginService { int key = rs1.getInt(_userTableKey); String credentials = rs1.getString(_userTablePasswordField); - List roles = new ArrayList(); - try (PreparedStatement statement2 = connection.prepareStatement(_roleSql)) - { - statement2.setInt(1, key); - try (ResultSet rs2 = statement2.executeQuery()) + + List roles = new ArrayList(); + try (PreparedStatement statement2 = connection.prepareStatement(_roleSql)) { - while (rs2.next()) + statement2.setInt(1, key); + try (ResultSet rs2 = statement2.executeQuery()) { - roles.add(rs2.getString(_roleTableRoleField)); + while (rs2.next()) + { + roles.add(rs2.getString(_roleTableRoleField)); + } } } - } - return putUser(userName, Credential.getCredential(credentials), roles.toArray(new String[roles.size()])); + return putUser(userName, Credential.getCredential(credentials), roles.toArray(new String[roles.size()])); } } } @@ -334,6 +362,83 @@ public class DataSourceLoginService extends MappedLoginService } + /** + * @see org.eclipse.jetty.security.MappedLoginService#loadUserInfo(java.lang.String) + * @Override + */ + public KnownUser loadUserInfo (String username) + { + try + { + try (Connection connection = getConnection(); + PreparedStatement statement1 = connection.prepareStatement(_userSql)) + { + statement1.setObject(1, username); + try (ResultSet rs1 = statement1.executeQuery()) + { + if (rs1.next()) + { + int key = rs1.getInt(_userTableKey); + String credentials = rs1.getString(_userTablePasswordField); + + return new DBUser(username, Credential.getCredential(credentials), key); + } + } + } + } + catch (NamingException e) + { + LOG.warn("No datasource for "+_jndiName, e); + } + catch (SQLException e) + { + LOG.warn("Problem loading user info for "+username, e); + } + return null; + } + + /** + * @see org.eclipse.jetty.security.MappedLoginService#loadRoleInfo(org.eclipse.jetty.security.MappedLoginService.KnownUser) + * @Override + */ + public String[] loadRoleInfo (KnownUser user) + { + DBUser dbuser = (DBUser)user; + + try + { + try (Connection connection = getConnection(); + PreparedStatement statement2 = connection.prepareStatement(_roleSql)) + { + + List roles = new ArrayList(); + + statement2.setInt(1, dbuser.getKey()); + try (ResultSet rs2 = statement2.executeQuery()) + { + while (rs2.next()) + { + roles.add(rs2.getString(_roleTableRoleField)); + } + + return roles.toArray(new String[roles.size()]); + } + } + } + catch (NamingException e) + { + LOG.warn("No datasource for "+_jndiName, e); + } + catch (SQLException e) + { + LOG.warn("Problem loading user info for "+user.getName(), e); + } + return null; + } + + + + /* ------------------------------------------------------------ */ @Override diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java index 5d606528eeb..659083b7cf6 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java @@ -19,7 +19,11 @@ package org.eclipse.jetty.security; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.eclipse.jetty.security.MappedLoginService.KnownUser; import org.eclipse.jetty.security.PropertyUserStore.UserListener; import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.util.Scanner; @@ -54,6 +58,36 @@ public class HashLoginService extends MappedLoginService implements UserListener private Resource _configResource; private Scanner _scanner; private boolean hotReload = false; // default is not to reload + + + + public class HashKnownUser extends KnownUser + { + String[] _roles; + + /** + * @param name + * @param credential + */ + public HashKnownUser(String name, Credential credential) + { + super(name, credential); + } + + + + public void setRoles (String[] roles) + { + _roles = roles; + } + + public String[] getRoles() + { + return _roles; + } + } + + /* ------------------------------------------------------------ */ public HashLoginService() @@ -163,6 +197,41 @@ public class HashLoginService extends MappedLoginService implements UserListener // TODO: Consider refactoring MappedLoginService to not have to override with unused methods } + + + @Override + protected String[] loadRoleInfo(KnownUser user) + { + UserIdentity id = _propertyUserStore.getUserIdentity(user.getName()); + if (id == null) + return null; + + + Set roles = id.getSubject().getPrincipals(RolePrincipal.class); + if (roles == null) + return null; + + List list = new ArrayList<>(); + for (RolePrincipal r:roles) + list.add(r.getName()); + + return list.toArray(new String[roles.size()]); + } + + @Override + protected KnownUser loadUserInfo(String userName) + { + UserIdentity id = _propertyUserStore.getUserIdentity(userName); + if (id != null) + { + return (KnownUser)id.getUserPrincipal(); + } + + return null; + } + + + /* ------------------------------------------------------------ */ /** * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() @@ -204,9 +273,11 @@ public class HashLoginService extends MappedLoginService implements UserListener { if (LOG.isDebugEnabled()) LOG.debug("update: " + userName + " Roles: " + roleArray.length); - putUser(userName,credential,roleArray); + //TODO need to remove and replace the authenticated user? } + + /* ------------------------------------------------------------ */ @Override public void remove(String userName) diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java index 089b8949117..9153064ae1e 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/JDBCLoginService.java @@ -77,6 +77,32 @@ public class JDBCLoginService extends MappedLoginService protected String _userSql; protected String _roleSql; + + /** + * JDBCKnownUser + * + * + */ + public class JDBCKnownUser extends KnownUser + { + int _userKey; + + /** + * @param name + * @param credential + */ + public JDBCKnownUser(String name, Credential credential, int key) + { + super(name, credential); + _userKey = key; + } + + + public int getUserKey () + { + return _userKey; + } + } /* ------------------------------------------------------------ */ public JDBCLoginService() @@ -231,7 +257,7 @@ public class JDBCLoginService extends MappedLoginService } /* ------------------------------------------------------------ */ - @Override + @Deprecated protected UserIdentity loadUser(String username) { try @@ -251,6 +277,8 @@ public class JDBCLoginService extends MappedLoginService { int key = rs1.getInt(_userTableKey); String credentials = rs1.getString(_userTablePasswordField); + + List roles = new ArrayList(); try (PreparedStatement stat2 = _con.prepareStatement(_roleSql)) @@ -262,7 +290,7 @@ public class JDBCLoginService extends MappedLoginService roles.add(rs2.getString(_roleTableRoleField)); } } - return putUser(username, credentials, roles.toArray(new String[roles.size()])); + return putUser(username, Credential.getCredential(credentials), roles.toArray(new String[roles.size()])); } } } @@ -274,12 +302,88 @@ public class JDBCLoginService extends MappedLoginService } return null; } - - /* ------------------------------------------------------------ */ - protected UserIdentity putUser (String username, String credentials, String[] roles) + + + /** + * @see org.eclipse.jetty.security.MappedLoginService#loadUserInfo(java.lang.String) + * @Override + */ + public KnownUser loadUserInfo (String username) { - return putUser(username, Credential.getCredential(credentials),roles); + try + { + if (null == _con) + connectDatabase(); + + if (null == _con) + throw new SQLException("Can't connect to database"); + + try (PreparedStatement stat1 = _con.prepareStatement(_userSql)) + { + stat1.setObject(1, username); + try (ResultSet rs1 = stat1.executeQuery()) + { + if (rs1.next()) + { + int key = rs1.getInt(_userTableKey); + String credentials = rs1.getString(_userTablePasswordField); + + return new JDBCKnownUser (username, Credential.getCredential(credentials), key); + } + } + } + } + catch (SQLException e) + { + LOG.warn("UserRealm " + getName() + " could not load user information from database", e); + closeConnection(); + } + + return null; } + + + + /** + * @see org.eclipse.jetty.security.MappedLoginService#loadRoleInfo(org.eclipse.jetty.security.MappedLoginService.KnownUser) + * @Override + */ + public String[] loadRoleInfo (KnownUser user) + { + JDBCKnownUser jdbcUser = (JDBCKnownUser)user; + + try + { + if (null == _con) + connectDatabase(); + + if (null == _con) + throw new SQLException("Can't connect to database"); + + + List roles = new ArrayList(); + + try (PreparedStatement stat2 = _con.prepareStatement(_roleSql)) + { + stat2.setInt(1, jdbcUser.getUserKey()); + try (ResultSet rs2 = stat2.executeQuery()) + { + while (rs2.next()) + roles.add(rs2.getString(_roleTableRoleField)); + return roles.toArray(new String[roles.size()]); + } + } + } + catch (SQLException e) + { + LOG.warn("UserRealm " + getName() + " could not load user information from database", e); + closeConnection(); + } + + return null; + } + + /** diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java index 70b4c953294..310a4db8bc2 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/MappedLoginService.java @@ -139,6 +139,8 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo public void logout(UserIdentity identity) { LOG.debug("logout {}",identity); + + //TODO should remove the user????? } /* ------------------------------------------------------------ */ @@ -200,6 +202,24 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo _users.put(userName,identity); return identity; } + + + + + public synchronized UserIdentity putUser (KnownUser userPrincipal, String[] roles) + { + Subject subject = new Subject(); + subject.getPrincipals().add(userPrincipal); + subject.getPrivateCredentials().add(userPrincipal._credential); + if (roles!=null) + for (String role : roles) + subject.getPrincipals().add(new RolePrincipal(role)); + subject.setReadOnly(); + UserIdentity identity=_identityService.newUserIdentity(subject,userPrincipal,roles); + _users.put(userPrincipal._name,identity); + return identity; + } + /* ------------------------------------------------------------ */ public void removeUser(String username) @@ -219,9 +239,17 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo UserIdentity user = _users.get(username); if (user==null) - user = loadUser(username); - - if (user!=null) + { + KnownUser userPrincipal = loadUserInfo(username); + if (userPrincipal.authenticate(credentials)) + { + //safe to load the roles + String[] roles = loadRoleInfo(userPrincipal); + user = putUser(userPrincipal, roles); + return user; + } + } + else { UserPrincipal principal = (UserPrincipal)user.getUserPrincipal(); if (principal.authenticate(credentials)) @@ -241,7 +269,10 @@ public abstract class MappedLoginService extends AbstractLifeCycle implements Lo return false; } - + /* ------------------------------------------------------------ */ + protected abstract String[] loadRoleInfo (KnownUser user); + /* ------------------------------------------------------------ */ + protected abstract KnownUser loadUserInfo (String username); /* ------------------------------------------------------------ */ protected abstract UserIdentity loadUser(String username); diff --git a/tests/test-webapps/test-jaas-webapp/pom.xml b/tests/test-webapps/test-jaas-webapp/pom.xml index 40e4c475b6e..5d2261b5818 100644 --- a/tests/test-webapps/test-jaas-webapp/pom.xml +++ b/tests/test-webapps/test-jaas-webapp/pom.xml @@ -50,6 +50,13 @@ + + + mysql + mysql-connector-java + 5.1.19 + + org.apache.maven.plugins diff --git a/tests/test-webapps/test-jaas-webapp/src/main/config/demo-base/etc/login.conf b/tests/test-webapps/test-jaas-webapp/src/main/config/demo-base/etc/login.conf index a97b0eddeeb..e26c7c58a68 100644 --- a/tests/test-webapps/test-jaas-webapp/src/main/config/demo-base/etc/login.conf +++ b/tests/test-webapps/test-jaas-webapp/src/main/config/demo-base/etc/login.conf @@ -1,5 +1,13 @@ xyz { -org.eclipse.jetty.jaas.spi.PropertyFileLoginModule required +org.eclipse.jetty.jaas.spi.JDBCLoginModule required debug="true" -file="${jetty.base}/etc/login.properties"; +userTable="users" +userField="username" +credentialField="pwd" +userRoleTable="userroles" +userRoleUserField="username" +userRoleRoleField="rolename" +dbDriver="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource" +dbUrl="jdbc:mysql://localhost:3306/jaas" +dbUserName="janb"; };