Our web application is deployed on Tomcat, currently using the UserDatabaseRealm for security. We want to supply a page in the application where the user can change their password - a simple, common web application function. I cannot find any example servlet code to do this. The Tomcat description of the UserDatabaseRealm implies that it can be updated programmatically after loading the XML when the server starts, and it can also save changes back to the XML file. There is a brief mention of JMX as a means, but no details.
Our goal is to have no database in this application, so we really don't want to use the JDBC Realm. What does the Java servlet code look like to change a user's password (and for an admin, to add/remove users)?
Thanks for the clues, here is my working Tomcat MemoryUserDatabase servlet (minus any encryption, password verification, error handling, etc):
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
// Get current password for currently authenticated user
String username = request.getRemoteUser();
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
ObjectName userObjName = new ObjectName("Users:type=User,username=\""+username+"\",database=UserDatabase");
Object password = server.getAttribute(userObjName, "password");
System.out.println("Current Password = "+password.toString());
// Get new password from request parms and update the DB
String newPw = request.getParameter("newpw");
server.setAttribute(userObjName, new Attribute("password", newPw));
// Password is updated in-memory, now write to file.
// Note Tomcat MemoryUserDatabase.save() implementation does not synchronize this
// operation, so it can fail badly if multiple users do this at the same time.
// Ugh. Should do this in a static synchronized method.
server.invoke(
new ObjectName("Users:type=UserDatabase,database=UserDatabase"),
"save",
new Object[0],
new String[0]);
// If no exception, save was OK (it returns VOID, so there is no return value to check)
}
catch (Throwable t) {
// Should return proper HTTP error code...
t.printStackTrace(System.err);
}
}
I just figures this out.
first you have to update the server.xml and add readonly=false to:
<Resource auth="Container" readonly="false" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
then in a jsp file:
/N