This was written in 2005 and as of the last year or so I haven’t done much Java Swing development work, due to this i’m unsure if any of the below still holds weight. Please use the information below only as a guide.
I cannot take credit for all of this work, some of the files in this page were created from skeleton files from the SwingLabs Project. Basically what these classes outlay is a working configuration of JXLoginDialog that authenticates against a table in a mysql database
Class is.ISLoginListener
This class is used to put the last successfull login into preferences so it can be read back and set in the loginPanel next time the user launches
/*
* ISLoginListener.java
*
* Created on 16 November 2005, 14:05
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package is;
import org.jdesktop.swingx.auth.*;
import org.jdesktop.swingx.JXLoginPanel;
/**
*
* @author Greg
*/
public class ISLoginListener implements LoginListener {
private JXLoginPanel panel;
public ISLoginListener(JXLoginPanel panel) {
this.panel = panel;
}
public void loginSucceeded(LoginEvent source) {
is.IS_Statics.prefs.putLastLogin(panel.getUserName());
}
public void loginStarted(LoginEvent source) {
}
public void loginFailed(LoginEvent source) {
}
public void loginCanceled(LoginEvent source) {
}
}
Class is.ISUserNameStore
The user name store is used to keep track of recent logins, providing a drop down box in the panel for users to select the username from.
package is;
import java.beans.PropertyChangeSupport;
import java.util.prefs.Preferences;
import org.jdesktop.swingx.JXLoginPanel;
import org.jdesktop.swingx.auth.UserNameStore;
/**
* Saves the user names in Preferences. Because any string could be part
* of the user name, for every user name that must be saved a new Preferences
* key/value pair must be stored.
*
*/
public class ISUserNameStore extends UserNameStore {
//The key for one of the preferences
private static final String USER_KEY = "usernames";
private static final String NUM_KEY = "usernames.length";
/**
* A name that is used when retrieving preferences. By default, the
* app name is "default". This should be set by the application
* if the application wants it's own list of user names.
*/
private static final String DEFAULT_APP_NAME = "default";
/**
* The preferences node
*/
private Preferences prefs;
/**
* Contains the user names. Since the list of user names is not
* frequently updated, there is no penalty in storing the values
* in an array.
*/
private String[] userNames;
/**
* Used for propogating bean changes
*/
private PropertyChangeSupport pcs;
/**
* Creates a new instance of DefaultUserNameStore
*/
public ISUserNameStore() {
System.err.println("Creating");
pcs = new PropertyChangeSupport(this);
userNames = new String[0];
loadUserNames();
}
/**
* Loads the user names from Preferences
*/
public void loadUserNames() {
System.err.println("Loading usernames");
initPrefs();
if (prefs != null) {
int n = prefs.getInt(NUM_KEY, 0);
String[] names = new String[n];
for (int i = 0; i < n; i++) {
names[i] = prefs.get(USER_KEY + "." + i, null);
}
setUserNames(names);
}
}
/**
* Saves the user names to Preferences
*/
public void saveUserNames() {
System.err.println("Saving Usernames");
initPrefs();
if (prefs != null) {
prefs.putInt(NUM_KEY, userNames.length);
for (int i = 0; i < userNames.length; i++) {
prefs.put(USER_KEY + "." + i, userNames[i]);
}
}
}
/**
* @inheritDoc
*/
public String[] getUserNames() {
System.err.println("Get Usernames");
return userNames;
}
/**
* @inheritDoc
*/
public void setUserNames(String[] userNames) {
System.err.println("Setting userNames array");
if (this.userNames != userNames) {
String[] old = this.userNames;
this.userNames = userNames == null ? new String[0] : userNames;
pcs.firePropertyChange("userNames", old, this.userNames);
}
}
/**
* Add a username to the store.
* @param name
*/
public void addUserName(String name) {
System.err.println("Adding "+name);
if (!containsUserName(name)) {
String[] newNames = new String[userNames.length + 1];
for (int i=0; i
newNames[i] = userNames[i];
}
newNames[newNames.length - 1] = name;
setUserNames(newNames);
}
}
/**
* Removes a username from the list.
*
* @param name
*/
public void removeUserName(String name) {
System.err.println("Removing "+name);
if (containsUserName(name)) {
String[] newNames = new String[userNames.length - 1];
int index = 0;
for (String s : userNames) {
if (!s.equals(name)) {
newNames[index++] = s;
}
}
setUserNames(newNames);
}
}
/**
* @inheritDoc
*/
public boolean containsUserName(String name) {
System.err.println("Contains "+name);
for (String s : userNames) {
if (s.equals(name)) {
return true;
}
}
return false;
}
/**
* @return Returns Preferences node in which the user names will be stored
*/
public Preferences getPreferences() {
System.err.println("get prefs");
return prefs;
}
/**
* @param prefs the Preferences node to store the user names in. If null,
* or undefined, then they are stored in /org/jdesktop/swingx/auth/DefaultUserNameStore.
*/
public void setPreferences(Preferences prefs) {
System.err.println("set prefs");
initPrefs();
if (this.prefs != prefs) {
Preferences old = this.prefs;
this.prefs = prefs;
pcs.firePropertyChange("preferences", old, prefs);
//if prefs is null, this next method will create the default prefs node
loadUserNames();
}
}
/**
* Creates the default prefs node
*/
private void initPrefs() {
System.err.println("init prefs");
if (prefs == null) {
prefs = Preferences.userNodeForPackage(isquote.Main.class);
// Use a relative path
prefs = Preferences.userRoot().node("/IS");
}
}
}
Class: is.ISLoginService
The magic happens here, the LoginService is what authenticates on behalf of the login panel, all you have to do is have the authenticate function return true or false based on whether the login succeeded or failed. Easy huh? As you can see this class is easily adaptable to reading usernames and passwords from anything you want.
package is;
import org.jdesktop.swingx.auth.LoginService;
import org.jdesktop.swingworker.SwingWorker;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* A login service for authenticating against a SQL Table using JDBC
*
* @author Greg Tangey
*/
public class ISLoginService extends LoginService {
private static final Logger LOG = Logger.getLogger(ISLoginService.class.getName());
private Connection con;
/**
* Creates a new LoginService and initializses it to connect.
*/
public ISLoginService() {
System.out.println("Created service");
}
public Connection getConnection() {
return con;
}
/**
* @param name user name
* @param password user password
* @param server Must be either a valid JDBC URL for the type of JDBC driver you are using,
* or must be a valid JNDIContext from which to get the database connection
*/
public boolean authenticate(final String username, char[] pass, String server) throws Exception {
String password = new String(pass);
final String md5password = is.MD5Hash.hash(password);
final String latestVersion;
String dbPassword = "";
Exception e;
try {
con = is.IS_Statics.ISPool.getConnection();
if (con != null) {
Statement s = con.createStatement();
ResultSet rs = s.executeQuery( "SELECT user_id,passphrase,access_level,homebin FROM users where `login` = \"" + username + "\"");
while (rs.next()) {
is.IS_Statics.userID = (rs.getInt ("user_id"));
is.IS_Statics.userLevel = (rs.getInt ("access_level"));
is.IS_Statics.userName = username;
dbPassword = (rs.getString("passphrase"));
}
rs.close();
}
else {
System.err.println("Connection NULL return false");
return false;
}
}
catch (SQLException e2) {
System.err.println(e2.toString());
System.out.println("Exception caught return false");
return false;
}
finally {
try {
con.close();
}
catch(SQLException e3) {
System.err.println(e3.toString());
}
}
if (md5password.equals(dbPassword) == true) {
is.IS_Statics.prefs.putLastLogin(username);
// clear the login/password from the dialog
setupApp();
System.out.println("Password correct return true");
return true;
}
else {
System.out.println("Password incorrect return false");
return false;
}
}
private void setupApp() {
/* I use this to get any kind of data from the database that doesnt change much and
* is used frequently */
}
}
How to initiate and display:
Below is how we initiate the LoginPanel with all its various extras and then show it as a modal dialog blocking a frame
// Create a new login service for use with the JXLoginPanel
is.ISLoginService service = new is.ISLoginService();
// Create new JXLoginPanel to use with the Diaog
is.IS_Statics.loginPanel = new JXLoginPanel(service, null, new is.ISUserNameStore(), null);
// Add Login listerner to the login service to handle placing the last login
// in preferences after the login is successfull
service.addLoginListener(new is.ISLoginListener(is.IS_Statics.loginPanel));
// Set the last successfull logins username from preferences
is.IS_Statics.loginPanel.setUserName(is.IS_Statics.prefs.getLastLogin());
// Show login dialog modal, blocking the mainFrame
// is.IS_Statics.mainFrame is thea Frame you want to the modal login dialog to block
// is.IS_Statics.loginPanel is the loginPanel we just created
org.jdesktop.swingx.JXLoginPanel.Status status = JXLoginPanel.showLoginDialog(is.IS_Statics.mainFrame,is.IS_Statics.loginPanel);
// If close button is pressed, or X on the dialog window, quit the app
if(status == JXLoginPanel.Status.CANCELLED || status == JXLoginPanel.Status.NOT_STARTED) {
is.IS_Statics.mainFrame.dispose();
}
very good article!