-->

how to programatically add users to tomcat UserDat

2020-07-18 23:32发布

问题:

I am having a simple Java web application with not more than 20-25 users who would be logged in. I am currently using tomcat server to host it and am using the UderDatabaseRealm for access control. I would like to add a feature to this application wherein the administrator can add users to the system through the application itself. I would like to know is it possible to programmatically add users to this file. One method I can think of is to open the tomcat_users.xml file within my application and do XML manipulation to add the users. Is there a better way than this?

My realm is configured in servers.xml as :-

<Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>

My tomcat_users.xml file is as follows:-
<tomcat-users>

  <role rolename="admin"/>
  <role rolename="local"/>
  <user username="tomcat" password="tomcat" roles="admin"/>
</tomcat-users>

回答1:

You can use JNDI to get the UserDatabase Object from your running tomcat with all information about your users and roles. You have to define your UserDatabase as global resource in your server.xml and add a resource link to your context.xml file like this:

server.xml

<GlobalNamingResources>

     <Resource auth="Container" description="User database that can be updated and saved"
        factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase"
        pathname="/home/user/tomcat-users.xml" type="org.apache.catalina.UserDatabase"
        readonly="false" />

</GlobalNamingResources>

<Realm className="org.apache.catalina.realm.LockOutRealm">

    <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>

</Realm>

context.xml of your webapp

<Context>

    <ResourceLink name="UserDatabase" global="UserDatabase"
        type="org.apache.catalina.UserDatabase" />

</Context>

Now you can use the InitialContext to get the UserDatabase Object:

UserDatabase ud = (UserDatabase) new InitialContext().lookup("java:comp/env/UserDatabase");

Now you can call methods of this Database like :

ud.createUser("username", "password", "fullname");

Don't forget to call the ud.save(); method so that the changes can be written to the xmlfile. To save this, the readonly attribute of the global resource has to be false.



回答2:

You can use something more flexible: a database. You need to configure a org.apache.catalina.realm.DataSourceRealm.

DB:

CREATE TABLE tomcat_users (
    user_name varchar(20) NOT NULL PRIMARY KEY,
    password varchar(250) NOT NULL
);
CREATE TABLE tomcat_roles (
    user_name varchar(20) NOT NULL,
    role_name varchar(20) NOT NULL,
    PRIMARY KEY (user_name, role_name) 
);

server.xml:

<Realm className="org.apache.catalina.realm.DataSourceRealm"
   dataSourceName="jdbc/auth"
   digest="MD5"
   userTable="tomcat_users" userNameCol="user_name" userCredCol="password"
   userRoleTable="tomcat_roles" roleNameCol="role_name"/>

context.xml:

<Resource name="jdbc/auth" auth="Container" type="javax.sql.DataSource"
   maxActive="100" maxIdle="30" maxWait="10000"
   username="realm_access" password="password" driverClassName="com.mysql.jdbc.Driver"
   url="jdbc:mysql://localhost:3306/tomcat_realm"/>

See full examples in http://wiki.apache.org/tomcat/TomcatDataSourceRealms and http://java.dzone.com/articles/setting-apache-tomcat-basic



回答3:

In terms of your original question, Tomcat reads tomcat-users.xml at startup and would not pick up any changes that were made to the file itself while the server is running. You would need to use JMX to interact with the UserDatabaseRealm MBean if you wanted to make changes dynamically at runtime.

The better option is almost certainly to switch to using a DataSourceRealm, as the earlier answer suggested.



回答4:

Another alternative is to use JMX as suggested by the Tomcat documentation. The following links will be probably helpful.

  • http://tomcat.apache.org/tomcat-7.0-doc/monitoring.html
  • http://tomcat.apache.org/tomcat-7.0-doc/funcspecs/mbean-names.html#MBean_Groups_and_Names

But as Paul Vargas said using a DataSourceRealm will be a much easier solution in this case.



回答5:

Here is a JSP example of how to add new users to the tomcat: first update the server.xml file, add readonly="false" attribute for the resource auth="Container":

<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:

ArrayList list = MBeanServerFactory.findMBeanServer(null);
MBeanServer mbeanServer = (MBeanServer) list.get(0);
ObjectName obname=new ObjectName("Users:type=UserDatabase,database=UserDatabase");
MBeanInfo info = mbeanServer.getMBeanInfo( obname );
Object name=mbeanServer.invoke(obname,"createUser",new String[]{"user","pwd","fname"},new String[]{String.class.getName(),String.class.getName(),String.class.getName()});
mbeanServer.invoke(obname,"save",new Object[0],new String[0]);

you can also change the password of a user see my answer: How to change a user's tomcat password in servlet application