Servlet container和Web应用程序本身都可以控制Web应用程序资源的安全防护。在J2EE规范中,前者成为容器管理(container-managed)的安全防护,后者称为应用程序管理(application-managed)的安全防护。为了使用Tomcat的容器管理的安全防护机制,必须设定领域。领域只是用户、密码和角色的集合。
Tomcat包含以下几个常见的领域实现:UserDatabaseRealm、JDBCRealm、JNDIRealm与JAASRealm。另外,开发者可以创建额外的领域实现,以便作为其用户和密码的接口。领域在server.xml文件中以<Realm>元素指定:
1<Realm className="some.realm.implementation.className" 2 customAttribute1="some value" 3 customAttribute2="other value"/>
UserDatabaseRealm
UserDatabaseRealm是从静态文件加载到内存中的,且直到Tomcat停止后才从内存中清除。事实上,Tomcat所用的用户、密码及角色只存在于内存中,换句话说,权限文件只会在启动时读入一次。在UserDatabaseRealm中分配权限的默认文件为$CATALINA_HOME/conf/tomcat-users.xml。
server.xml中resource的声明:
1<Resource name="UserDatabase" auth="Container" 2 type="org.apache.catalina.UserDatabase" 3 description="User database that can be updated and saved" 4 factory="org.apache.catalina.users.MemoryUserDatabaseFactory" 5 pathname="conf/tomcat-users.xml" />
server.xml中UserDatabaseRealm的配置:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
tomcat-users.xml中users和roles的配置:
1<tomcat-users xmlns="http://tomcat.apache.org/xml" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd" 4 version="1.0"> 5 <role rolename="tomcat"/> 6 <role rolename="role1"/> 7 <user username="tomcat" password="tomcat" roles="tomcat"/> 8 <user username="both" password="tomcat" roles="tomcat,role1"/> 9 <user username="role1" password="tomcat" roles="role1"/> 10</tomcat-users>
user和password的意义很清楚了,不过这里要解释一下有关roles的含义。角色(roles)是一组用户,针对这组用户,Web应用程序可以定义一组特定的功能组合。
UserDatabaseRealm并非真正用于实际,因为它唯一的更新方式是编写能经由JNDI访问Realm的自定义servlet。而该servlet需要能修改内存中的用户数据库,或磁盘上的tomcat-users.xml文件,最后,还需要重启Tomcat以便使这些修改生效。
JDBCRealm
顾名思义,JDBCRealm是一个可以使用关系型数据库的领域。它比UserDatabaseRealm更灵活,并且能动态的访问数据库。例如:往数据库中新增一个账号,JDBCRealm就可以马上读取它。
server.xml中JDBCRealm的配置:
1<Realm className="org.apache.catalina.realm.JDBCRealm" debug="99" 2 driverName="com.mysql.jdbc.Driver" 3 connectionURL="jdbc:mysql://localhost:3306/DB_NAME" 4 connectionName="DB_Username" 5 connectionPassword="DB_Password" 6 userTable="TABLE_Name" 7 userNameCol="COLUMN_Username" 8 userCredCol="COLUMN_Password" 9 userRoleTable="ROLE_TABLE_Name" 10 roleNameCol="COLUMN_Role" />
DataSourceRealm
这是一个通过JNDI访问配置好的数据源,来访问关系型数据库的一种Realm实现。
假如有个MySQL数据库叫"authority",并且包含下面的表:
1create table users ( 2 user_name varchar(15) not null primary key, 3 user_pass varchar(15) not null 4); 5 6create table user_roles ( 7 user_name varchar(15) not null, 8 role_name varchar(15) not null, 9 primary key (user_name, role_name) 10);
如果可以通过JNDI方式以"java:/comp/env/jdbc/authority"访问,此时:
server.xml中配置DataSourceRealm:
1<Realm className="org.apache.catalina.realm.DataSourceRealm" 2 dataSourceName="jdbc/authority" 3 userTable="users" 4 userNameCol="user_name" 5 userCredCol="user_pass" 6 userRoleTable="user_roles" 7 roleNameCol="role_name"/>
JNDIRealm
如果需要Tomcat从LDAP(Lightweight Directory Access Protocol,轻量目录访问协议)目录取得用户名称、角色及密码,则可以使用JNDIReam。它是一个非常有弹性的Realm实现,可以依据用户名、角色及密码的LDAP目录来验证用户的身份。同时还允许该数据用于许多不同的模式布局。它还可以递归的搜寻LDAP的层次目录,直到找到所需的信息为止。还可以在特定服务器的特定位置查找。
server.xml中JNDIRealm的配置:
1<Realm className="org.apache.catalina.realm.JNDIRealm" 2 connectionURL="ldap://localhost:389" 3 userPattern="uid={0},ou=people,dc=mycompany,dc=com" 4 roleBase="ou=groups,dc=mycompany,dc=com" 5 roleName="cn" 6 roleSearch="(uniqueMember={0})"/>
JAASRealm
JAASRealm是经由JAAS(Java Authentication and Authorization Service,Java验证与授权服务)验证用户的一种领域实现。JAAS实现了标准的“可插入式验证模块(Pluggable Authentication Module,PAM)”架构,此架构可让应用程序独立于验证实现之外。可以不修改应用程序本身而只需稍微修改应用程序的配置,在应用程序中插入全新或更新的验证实现。除此之外,JAAS还支持堆栈式的验证模块,从而在一个验证堆栈中,多个验证模块可以相互协同使用。
1<Realm className="org.apache.catalina.realm.JAASRealm" 2 appName="MyFooRealm" 3 userClassNames="org.foobar.realm.FooUser" 4 roleClassNames="org.foobar.realm.FooRole"/>
CombinedRealm
这是一个特殊的Realm,顾名思义,它可以使用多个子的Realm(Realm可以嵌套)来对用户进行授权。也许你有多个“数据源”,也许你希望当有一个Realm停止工作的时候系统仍然不会崩溃,不管是什么需求需要同时使用多个Realm,这个CombinedRealm就能满足这个需求。授权将会按照子Realm的声明顺序依次进行,只要满足任何一个子Realm,都可以通过校验。
1<Realm className="org.apache.catalina.realm.CombinedRealm" > 2 <Realm className="org.apache.catalina.realm.UserDatabaseRealm" 3 resourceName="UserDatabase"/> 4 <Realm className="org.apache.catalina.realm.DataSourceRealm" 5 dataSourceName="jdbc/authority" 6 userTable="users" 7 userNameCol="user_name" 8 userCredCol="user_pass" 9 userRoleTable="user_roles" 10 roleNameCol="role_name"/> 11</Realm>
LockOutRealm
它继承与CombinedRealm,和CombinedRealm一样,与它一起工作的Realm需要嵌套在LockOutRealm中,而且也是只需要满足任何一个Realm即可。如果在一定的时间内多次尝试授权失败,它将会锁定这个用户。使用它时,不需要修改它下面的Realm配置,因为它是通过记录所有失败的登录(包括不存在的用户)来实现的。
下面是安装Tomcat后,server.xml中默认的配置:
1<!-- Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack --> 2<Realm className="org.apache.catalina.realm.LockOutRealm"> 3 <!-- This Realm uses the UserDatabase configured in the global JNDI resources under the key 4 "UserDatabase". Any edits that are performed against this UserDatabase are immediately 5 available for use by the Realm. --> 6 <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> 7</Realm>
参考链接:
http://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html#UserDatabaseRealm