我有一个简单的Java web应用程序,登录用户不超过20-25人。我目前使用tomcat服务器托管它,并使用UderDatabaseRealm进行访问控制。我想为这个应用程序添加一个功能,管理员可以通过应用程序本身将用户添加到系统中。我想知道是否可以通过编程将用户添加到该文件中。我能想到的一种方法是在我的应用程序中打开tomcat_users.xml文件,并进行xml操作来添加用户。还有比这更好的方法吗?
我的领域在servers.xml中配置为:-
<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>
您可以使用JNDI从正在运行的tomcat中获取UserDatabase对象,其中包含有关用户和角色的所有信息。您必须在server.xml中将UserDatabase定义为全局资源,并向context.xml文件添加一个资源链接,如下所示:
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
<Context>
<ResourceLink name="UserDatabase" global="UserDatabase"
type="org.apache.catalina.UserDatabase" />
</Context>
现在您可以使用InitialContext来获取UserDatabase对象:
UserDatabase ud = (UserDatabase) new InitialContext().lookup("java:comp/env/UserDatabase");
现在你可以调用这个数据库的方法,比如:
ud.createUser("username", "password", "fullname");
不要忘记调用ud.save();
方法,以便可以将更改写入xml文件。要保存此项,全局资源的只读属性必须为false。
您可以使用更灵活的东西:数据库。您需要配置org.apache.catalina.realm.DataSourceRealm
。
数据库:
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"/>
请参阅中的完整示例http://wiki.apache.org/tomcat/TomcatDataSourceRealms和http://java.dzone.com/articles/setting-apache-tomcat-basic
根据您最初的问题,Tomcat在启动时读取Tomcat-users.xml,并且不会在服务器运行时对文件本身进行任何更改。如果希望在运行时动态地进行更改,则需要使用JMX与UserDatabaseRealm
MBean进行交互。
几乎可以肯定的是,更好的选择是切换到使用DataSourceRealm,正如前面的答案所建议的那样。
另一种选择是按照Tomcat文档的建议使用JMX。以下链接可能会有所帮助。
- 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
但正如Paul Vargas所说,在这种情况下,使用DataSourceRealm将是一个更容易的解决方案。
下面是一个如何向tomcat添加新用户的JSP示例:首先更新server.xml
文件,为资源auth="Container"
:添加readonly="false"
属性
<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"/>
然后在jsp文件中:
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]);
你也可以更改用户的密码查看我的答案:如何在servlet应用程序中更改用户的tomcat密码