链接 用户指南 参考 开发 Tomcat | The Apache Jakarta Tomcat 5 Servlet/JSP ContainerRealm Configuration HOW-TO |  print-friendly 版本 |
| 快速上手(Quick Start) |
这个文档资料描述了怎样通过连接一个现有"数据库"里的用户名称,密码以及角色来配置Tomcat,从而来支持容器管理的安全性(container managed security)。如果你使用一个网络程序,而这个程序里包括了一个或多个<security-constraint>元素,以及一个定义用户怎样认证他们自己的<login-config>元素,那你就要关心这些(指Realm Configuration)。如果你不使用这些特性,你就可以跳过这个文档资料。
参看 Servlet Specification (2.3 版),第12章,来了解容器管理安全性的基础背景知识。对于网络程序开发员和管理员来说,要了解初级水平的文件,请看(FIXME - 链接到关于容器管理安全性的背景知识)。
关于使用Tomcat 5的一次性登录特性(允许用户只需认证他自己一次就可以使用和虚拟主机相关的所有网络程序)的信息。请看这里。
|
| 概述 |
| 什么是Realm? (What is a Realm?) |
一个Realm就是一个由用户名称和识别用户的密码组成的“数据库”,以及与每个合法的用户相关联的一系列角色列举。因为具有某一特殊角色的所有用户都可以被允许访问(access)特定的网络应用资源(而不是列举相关的用户名称),你可以认为这些角色类似于Unix-like操作系统的用户群组(groups)。一个特定的用户可以有许多和用户名称相关联的角色。
尽管Servlet规范描述了一个可以让应用程序声明它们安全性要求(在web.xml部署描述符里)的可携带机制,但是还没有可携带的API(应用编程接口)来定义一个基于servlet容器和相关用户角色之间的界面(interface)。然而在许多情况下,最好能把一个servlet容器和那些已经存在于生产环境中的认证数据库或机制“连接”起来。因此,Tomcat 5定义了一个Java界面(org.apache.catalina.Realm),它可以通过"plug in"来实现这种连接。这里提供了三个标准的plug-ins ,用来支持和三个不同来源的认证信息的连接:
- DataSourceRealm - 通过一个叫做JNDI JDBC 的数据源(DataSource)来访问贮存在关系数据库(relational database)里的认证信息。
- JDBCRealm - 通过JDBC驱动来访问贮存在关系数据库里的认证信息。
- JNDIRealm - 通过JNDI provider来访问贮存在基于LDAP(轻量目录访问协议)的目录服务器里的认证信息。
- MemoryRealm - 访问贮存在in-memory object collection里的认证信息,这个in-memory object collection是由一个XML文件(
conf/tomcat-users.xml)来进行初始化的。
也可以编写自己的Realm实现(implementation),并把它整合到Tomcat 5中去。然而,关于怎样做超过了这个文献的范围。详细信息请看(FIXME - reference to developer stuff)。
|
|
| 标准Realm实现(Standard Realm Implementations) |
| JDBCRealm |
简介
JDBCRealm是一个Tomcat 5 Realm界面实现,它通过JDBC驱动来查看关系数据库里的用户信息。这里配置的可塑性很大,它让你能够使用现存的表名和列名(column names),只要你的数据库结构与下面的要求一致:
- 必须要有一个表格(table)存在,它必须是每一行包含一个这个
Realm所能识别的合法用户。下面引用叫做users的表格。
- 这个用户表格必须包括至少两列(如果你的程序需要还可以有更多列)。
- 可被Tomcat识别的用户登录名称(username)。
- 可被Tomcat识别的用户登录密码。这个值可以是明文式(cleartext)或是被编码过(digested)的形式 - 下面可查看更多信息。
- 必须要有一个表格存在,它必须是每一行包含一个指派给某个特定用户的某个合法角色。下面引用叫做用户角色的表格。
- 这个用户角色表格必须包括至少两列(如果你的程序需要还可以有更多列):
- 可被Tomcat识别的用户登录名称(和users table里指定的值相同)。
- 和这个用户相关联的有效角色名称。
快速上手(Quick Start)
要设置好Tomcat来使用JDBCRealm,你必须遵守下面这些步骤:
- 根据上面所描述的规定,在你的数据库里产生表格(tables)和列(columns)。
- 配置一个可供Tomcat使用的用户名称和密码,它至少应该有只读(read only)权限来访问上述表格。(Tomcat从不会试图去改写这些表格)。
- 把你将要使用的JDBC驱动复制件放置到$CATALINA_HOME/server/lib目录(如果你不想让网络程序使用它的话)或者放在$CATALINA_HOME/common/lib(如果Tomcat 5和你的程序都要使用它的话)。注意,唯一只有JAR文件才能被识别。
- 象下面所描述的那样,在你的$CATALINA_HOME/conf/server.xml文件设置一个
<Realm>元素。
- 如果Tomcat 5已经在运行,重新启动它。
Realm元素属性
要配置JDBCRealm,你要产生一个<Realm>元素并把它套嵌在$CATALINA_HOME/conf/server.xml文件里,就如上面所描述那样。下面的这些属性被这一实现(this implementation)所支持:
| 属性 | 描述 |
|---|
className |
这个Realm实现的完全合格Java类名字。你必须在这里指定值为 "org.apache.catalina.realm.JDBCRealm" 。
| connectionName |
建立JDBC连接时使用的数据库用户名称。
| connectionPassword |
建立JDBC连接时使用的数据库用户密码。
| connectionURL |
建立JDBC连接时使用的数据库URL 。
| debug |
由这个Realm记录到相关的Logger上的排错(debugging)细节标准。数码越高,输出就越详细。如果没指定,那么默认的排错细节标准是零(0) 。
| digest |
用来以非明文形式贮存密码的“文摘”算法,那些被java.security.MessageDigest类里所接受的算法名称的值才是有效的值。更多信息请参见Digested 密码。如果没指定,密码以明文形式贮存。
| driverName |
被使用的JDBC驱动的充分合格的Java类名。查阅关于JDBC驱动的文献去寻找适当的值。
| roleNameCol |
用户角色表格中的列名,它包含分配给这名用户的角色名称。
| userCredCol |
用户表格中的列名,它包含了用户的密码(以明文的形式,或者被编码过的形式——如果这个digest 属性被设置)。
| userNameCol |
在用户和用户角色表格中的列名,它包含了这名用户的用户名称。 user roles
| userRoleTable |
表名,它的每一行包含指派给某一特定用户名称的一个角色。这个表格必须至少包括那些由userNameCol和roleNameCol属性定名的列。
| userTable |
表名,它的每一行包含一个可被Tomcat识别的用户名称。这个表格必须至少包括那些由userNameCol 和 userCredCol 属性定名的列。
|
例子
一个用于产生所需表格的SQL script示例也许看起来象这样(根据你特定的数据库需要做些语法上的改编):
 |  |  |  | create table users (
user_name varchar(15) not null primary key,
user_pass varchar(15) not null
);
create table user_roles (
user_name varchar(15) not null,
role_name varchar(15) not null,
primary key (user_name, role_name)
); |  |  |  |  |
关于Realm元素的例子被包括在默认的$CATALINA_HOME/conf/server.xml文件里(但被 commented out)。在下面的例子中,使用了一个叫做"authority"的MySQL数据库,根据上面所描述的表格进行了配置,可以通过用户名"dbuser" 和密码"dbpass"进行访问:
 |  |  |  | <Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://localhost/authority?user=dbuser&password=dbpass"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name"/> |  |  |  |  |
另外的注意事项
JDBCRealm根据下面的规则进行运作:
- 当一个用户第一次试图访问被保护的资源时,Tomcat 5会传叫(call)这个
Realm的authenticate()方法。因此,你对于这个数据库所做的认何直接更改(新用户,更改过的密码和角色等等)都会被立即反映出来。
- 一但用户被认证,用户(以及其相关角色)在这个用户登录期间会被高速缓存(cache)在Tomcat里。(对于是基于表单(FORM-based)认证的用户,在会话结束或者注销后认证失效;对于BASIC认证的用户,要等到用户关闭窗口后认证才失效)。被高速缓存的用户不会在会话系列之间被贮存或再生(restored)。对于已经被认证的用户,任何有关数据库信息的更改,一直要等到下次用户再次登录后才会被显示出来。 not
not
- 管理用户和用户角色表格里的信息应该是你的应用程序的职责。Tomcat没有提供任何built-in 能力来维护用户及其角色信息。 user roles

- 由这个
Realm记录的排错和异常消息被记录在Logger上,这个Logger与周围的Context , Host , 或 Engine 相关联。在默认的情况下,这个相应的Logger会在$CATALINA_HOME/logs 目录里产生一个日志文件。 Host
|
| DataSourceRealm |
简介
DataSourceRealm是一个Tomcat 5 Realm界面实现,它通过一个叫做JDBC DataSource的JNDI来访问查询关系数据库里的用户信息。这里配置的可塑性很大,让你能够使用现有的表名和列名,只要你的数据库结构与下面的要求一致:
- 必须要有一个表格(table)存在,它必须是每一行包含一个这个
Realm所能识别的合法用户。下面引用叫做users的表格。
- 这个用户表格必须包括至少两列(如果你的程序需要还可以有更多列)。
- 可被Tomcat识别的用户登录名称(username)。
- 可被Tomcat识别的用户登录密码。这个值可以是明文式(cleartext)或是被编码过(digested)的形式 - 下面可查看更多信息。
- 必须要有一个表格存在,它必须是每一行包含一个指派给某个特定用户的某个合法角色。下面引用叫做用户角色的表格。
- 这个用户角色表格必须包括至少两列(如果你的程序需要还可以有更多列):
- 可被Tomcat识别的用户登录名称(和users table里指定的值相同)。
- 和这个用户相关联的有效角色名称。
快速上手(Quick Start)
要设置好Tomcat来使用DataSourceRealm,你必须遵守下面这些步骤:
- 根据上面所描述的规定,在你的数据库里产生表格(tables)和列(columns)。
- 配置一个可供Tomcat使用的用户名称和密码,它至少应该有只读(read only)权限来访问上述表格。(Tomcat从不会试图去改写这些表格)。
- 为你的数据库配置一个叫做JDBC DataSource的JNDI。关于怎样配置一个叫做JDBC DataSource的JNDI的信息请参看JNDI DataSource Example HOW-TO 。
- 象下面所描述的那样,在你的$CATALINA_HOME/conf/server.xml文件设置一个
<Realm>元素。
- 如果Tomcat 5已经在运行,重新启动它。
Realm元素属性
要配置DataSourceRealm,你要产生一个<Realm>元素并把它套嵌在$CATALINA_HOME/conf/server.xml 文件里,就如上面所描述那样。下面的这些属性被这一实现(this implementation)所支持:
| 属性 | 描述 |
|---|
className |
这个Realm实现的完全合格Java类名字。你必须在这里指定值为 " org.apache.catalina.realm.DataSourceRealm "。
| dataSourceName |
你的数据库需要的一个叫做JDBC DataSource的JNDI。如果这个DataSource对于上下文来说是局部的话,这个名字与java:/comp/env相关,否则这个名字应该和定义全球性DataSource的名字相映射。
| debug |
由这个Realm记录到相关的Logger上的排错(debugging)细节标准。数码越高,输出就越详细。如果没指定,那么默认的排错细节标准是零(0) 。
| digest |
用来以非明文形式贮存密码的“文摘”算法,那些被java.security.MessageDigest类里所接受的算法名称的值才是有效的值。更多信息请参见Digested 密码。如果没指定,密码以明文形式贮存。
| localDataSource |
当这个realm被套嵌在一个Context元素里边,就允许这个realm使用为这个Context定义的DataSource,而不是全球性DataSource 。如果没有指定,默认值是false:使用全球性DataSource 。
| roleNameCol |
用户角色表格中的列名,它包含分配给这名用户的角色名称。
| userCredCol |
用户表格中的列名,它包含了用户的密码(以明文的形式,或者被编码过的形式——如果这个digest 属性被设置)。
| userNameCol |
在用户和用户角色表格中的列名,它包含了这名用户的用户名称。 user roles
| userRoleTable |
表名,它的每一行包含指派给某一特定用户名称的一个角色。这个表格必须至少包括那些由userNameCol和roleNameCol属性定名的列。
| userTable |
表名,它的每一行包含一个可被Tomcat识别的用户名称。这个表格必须至少包括那些由userNameCol 和 userCredCol 属性定名的列。
|
例子
一个用于产生所需表格的SQL script示例也许看起来象这样(根据你特定的数据库需要做些语法上的改编):
 |  |  |  | create table users (
user_name varchar(15) not null primary key,
user_pass varchar(15) not null
);
create table user_roles (
user_name varchar(15) not null,
role_name varchar(15) not null,
primary key (user_name, role_name)
); |  |  |  |  |
在下面的例子中,使用了一个叫做"authority"的MySQL数据库,根据上面所描述的表格进行了配置,可以通过"java:/comp/env/jdbc/authority"访问JNDI JDBC DataSource:
 |  |  |  | <Realm className="org.apache.catalina.realm.DataSourceRealm" debug="99"
dataSourceName="jdbc/authority"
userTable="users" userNameCol="user_name" userCredCol="user_pass"
userRoleTable="user_roles" roleNameCol="role_name"/> |  |  |  |  |
另外的注意事项
DataSourceRealm根据下面的规则进行运作:
- 当一个用户第一次试图访问被保护的资源时,Tomcat 5会传叫(call)这个
Realm的authenticate()方法。因此,你对于这个数据库所做的认何直接更改(新用户,更改过的密码和角色等等)都会被立即反映出来。
- 一但用户被认证,用户(以及其相关角色)在这个用户登录期间会被高速缓存(cache)在Tomcat里。(对于是基于表单(FORM-based)认证的用户,在会话结束或者注销后认证失效;对于BASIC认证的用户,要等到用户关闭窗口后认证才失效)。被高速缓存的用户不会在会话系列之间被贮存或再生(restored)。对于已经被认证的用户,任何有关数据库信息的更改,一直要等到下次用户再次登录后才会被显示出来。 not
not
- 管理用户和用户角色表格里的信息应该是你的应用程序的职责。Tomcat没有提供任何built-in 能力来维护用户及其角色信息。 user roles

- 由这个
Realm记录的排错和异常消息被记录在Logger上,这个Logger与周围的Context , Host , 或 Engine 相关联。在默认的情况下,这个相应的Logger会在$CATALINA_HOME/logs 目录里产生一个日志文件。 Host
|
| JNDIRealm |
简介
DataSourceRealm是一个Tomcat 5 Realm界面实现,它通过一个JNDI provider 来访问查询LDAP目录里的用户信息(通常是与JNDI API类一起的标准LDAP
provider)。这个realm支持一系列使用目录来进行认证的方法。 JNDIRealm
与目录相连接
这个realm与目录的连接是由connectionURL配置属性定义的。这个URL的格式又是由JNDI provider来定义的。它通常是一个LDAP URL,用来指定相连接的目录服务器的领域名称,或者端口数码以及所需的root naming context的特殊名称。
如果你有不止一个供应者(provider),你可以配置一个alternateURL。如果不能在connectionURL与供应者连接上,机器就会试图使用alternateURL来连接。
在为了查询目录和搜索用户及其角色进行连接的时候,这个realm就通过connectionName 和 connectionPassword 属性指定的用户名称和密码来向这个目录认证它自己。如果属性没有被指定,连接就是无名的。在许多情形下,这也足够了。
选择用户的目录进入
每一个能被认证的用户必须在目录里由一个单个登录(individual entry)来代表,这个单个登录与初始DirContext里边被connectionURL属性定义的一个元素相对应。这个用户登录必须有一个包含认证用的用户名称的属性(attribute).
通常这个用户登录的特殊名称包含提供给认证用的用户名,否则所有用户都一样。在这种情况下,userPattern这个属性也许可用来指定DN(特殊名称),用"{0}" 来标记可被替代的用户名。??????
否则这个realm必须搜寻(search)目录才能找到包含用户名称的独特的登录。这样的搜寻由下面的这些属性配置:
- userBase - the entry that is the base of
the subtree containing users. If not specified, the search
base is the top-level context.
- userSubtree - the search scope. Set to
true if you wish to search the entire subtree
rooted at the userBase entry. The default value
of false requests a single-level search
including only the top level.
- userSearch - pattern specifying the LDAP
search filter to use after substitution of the username.
认证用户
-
Bind mode
By default the realm authenticates a user by binding to
the directory with the DN of the entry for that user and the password
presented by the user. If this simple bind succeeds the user is considered to
be authenticated.
For security reasons a directory may store a digest of the user's
password rather than the clear text version (see Digested Passwords for more information). In that case,
as part of the simple bind operation the directory automatically
computes the correct digest of the plaintext password presented by the
user before validating it against the stored value. In bind mode,
therefore, the realm is not involved in digest processing. The
digest attribute is not used, and will be ignored if
set.
-
Comparison mode
Alternatively, the realm may retrieve the stored
password from the directory and compare it explicitly with the value
presented by the user. This mode is configured by setting the
userPassword attribute to the name of a directory
attribute in the user's entry that contains the password.
Comparison mode has some disadvantages. First, the
connectionName and
connectionPassword attributes must be configured to
allow the realm to read users' passwords in the directory. For
security reasons this is generally undesirable; indeed many directory
implementations will not allow even the directory manager to read
these passwords. In addition, the realm must handle password digests
itself, including variations in the algorithms used and ways of
representing password hashes in the directory. However, the realm may
sometimes need access to the stored password, for example to support
HTTP Digest Access Authentication (RFC 2069). (Note that HTTP digest
authentication is different from the storage of password digests in
the repository for user information as discussed above).
给用户指派角色
The directory realm supports two approaches to the representation
of roles in the directory:
-
Roles as explicit directory entries
Roles may be represented by explicit directory entries. A role
entry is usually an LDAP group entry with one attribute
containing the name of the role and another whose values are the
distinguished names or usernames of the users in that role. The
following attributes configure a directory search to
find the names of roles associated with the authenticated user:
- roleBase - the base entry for the role search.
If not specified, the search base is the top-level directory
context.
- roleSubtree - the search
scope. Set to
true if you wish to search the entire
subtree rooted at the roleBase entry. The default
value of false requests a single-level search
including the top level only.
- roleSearch - the LDAP search filter for
selecting role entries. It optionally includes pattern
replacements "{0}" for the distinguished name and/or "{1}" for the
username of the authenticated user.
- roleName - the attribute in a role entry
containing the name of that role.
A combination of both approaches to role representation may be used.
快速上手(Quick Start)
要设置好Tomcat来使用JNDIRealm,你必须遵守下面这些步骤:
- 确保你的目录服务器是依据上面的要求配置的。
- 如果需要,配置一个可供Tomcat使用的用户名称和密码,它应该有只读(read only)权限来访问上述表格。(Tomcat从不会试图去改写这些表格)。
- 把你将要使用的JNDI驱动(通常
ldap.jar available with JNDI)复制件放置到$CATALINA_HOME/server/lib目录(如果你不想让网络程序使用它的话)或者放在$CATALINA_HOME/common/lib(如果Tomcat 5和你的程序都要使用它的话)。
- 象下面所描述的那样,在你的$CATALINA_HOME/conf/server.xml文件设置一个
<Realm>元素。
- 如果Tomcat 5已经在运行,重新启动它。
Realm元素属性
要配置JNDIRealm,你要产生一个<Realm>元素并把它套嵌在$CATALINA_HOME/conf/server.xml 文件里,就如上面所描述那样。下面的这些属性被这一实现(this implementation)所支持:
| 属性 | 描述 |
|---|
className |
The fully qualified Java class name of this Realm implementation.
You MUST specify the value
"org.apache.catalina.realm.JNDIRealm" here.
| connectionName |
The directory username to use when establishing a
connection to the directory for LDAP search operations. If not
specified an anonymous connection is made, which is often
sufficient unless you specify the userPassword
property.
| connectionPassword |
The directory password to use when establishing a
connection to the directory for LDAP search operations. If not
specified an anonymous connection is made, which is often
sufficient unless you specify the userPassword
property.
| connectionURL |
The connection URL to be passed to the JNDI driver when
establishing a connection to the directory.
| contextFactory |
The fully qualified Java class name of the JNDI context
factory to be used for this connection. By default, the standard
JNDI LDAP provider is used
(com.sun.jndi.ldap.LdapCtxFactory).
| debug |
由这个Realm记录到相关的Logger上的排错(debugging)细节标准。数码越高,输出就越详细。如果没指定,那么默认的排错细节标准是零(0) 。
| digest |
The digest algorithm to apply to the plaintext password offered
by the user before comparing it with the value retrieved from the
directory. Valid values are those accepted for the algorithm name
by the java.security.MessageDigest class. See Digested Passwords for more
information. If not specified the plaintext password is assumed to
be retrieved. Not required unless userPassword is
specified
| roleBase |
The base directory entry for performing role searches. If
not specified, the top level element in the directory context
will be used.
| roleName |
The name of the attribute that contains role names in the
directory entries found by a role search. In addition you can
use the userRoleName property to specify the name
of an attribute, in the user's entry, containing additional
role names. If roleName is not specified a role
search does not take place, and roles are taken only from the
user's entry.
| roleSearch |
The LDAP filter expression used for performing role
searches, following the syntax supported by the
java.text.MessageFormat class. Use
{0} to substitute the distinguished name (DN) of
the user, and/or {1} to substitute the
username. If not specified a role search does not take place
and roles are taken only from the attribute in the user's
entry specified by the userRoleName property.
| roleSubtree |
Set to true if you want to search the entire
subtree of the element specified by the roleBase
property for role entries associated with the user. The
default value of false causes only the top level
to be searched.
| userBase |
The base element for user searches performed using the
userSearch expression. If not specified, the top
level element in the directory context will be used. Not used
if you are using the userPattern expression.
| userPassword |
Name of the attribute in the user's entry containing the
user's password. If you specify this value, JNDIRealm will
bind to the directory using the values specified by
connectionName and
connectionPassword properties, and retrieve the
corresponding attribute for comparison to the value specified
by the user being authenticated. If the digest
attribute is set, the specified digest algorithm is applied to
the password offered by the user before comparing it with the
value retrieved from the directory. If you do
not specify this value, JNDIRealm will
attempt a simple bind to the directory using the DN of the
user's entry and password specified by the user, with a
successful bind being interpreted as an authenticated
user.
| userPattern |
A pattern for the distinguished name (DN) of the user's
directory entry, following the syntax supported by the
java.text.MessageFormat class with
{0} marking where the actual username should be
inserted. You can use this property instead of
userSearch, userSubtree and
userBase when the distinguished name contains the
username and is otherwise the same for all users.
| userRoleName |
The name of an attribute in the user's directory entry
containing zero or more values for the names of roles assigned
to this user. In addition you can use the
roleName property to specify the name of an
attribute to be retrieved from individual role entries found
by searching the directory. If userRoleName is
not specified all the roles for a user derive from the role
search.
| userSearch |
The LDAP filter expression to use when searching for a
user's directory entry, with {0} marking where
the actual username should be inserted. Use this property
(along with the userBase and
userSubtree properties) instead of
userPattern to search the directory for the
user's entry.
| userSubtree |
Set to true if you want to search the entire
subtree of the element specified by the userBase
property for the user's entry. The default value of
false causes only the top level to be searched.
Not used if you are using the userPattern
expression.
|
例子
Creation of the appropriate schema in your directory server is beyond the
scope of this document, because it is unique to each directory server
implementation. In the examples below, we will assume that you are using a
distribution of the OpenLDAP directory server (version 2.0.11 or later), which
can be downloaded from
http://www.openldap.org. Assume that
your slapd.conf file contains the following settings
(among others):
 |  |  |  |
database ldbm
suffix dc="mycompany",dc="com"
rootdn "cn=Manager,dc=mycompany,dc=com"
rootpw secret
|  |  |  |  |
We will assume for connectionURL that the directory
server runs on the same machine as Tomcat. See http://java.sun.com/products/jndi/docs.html
for more information about configuring and using the JNDI LDAP
provider.
Next, assume that this directory server has been populated with elements
as shown below (in LDIF format):
 |  |  |  |
# Define top-level entry
dn: dc=mycompany,dc=com
objectClass: dcObject
dc:mycompany
# Define an entry to contain people
# searches for users are based on this entry
dn: ou=people,dc=mycompany,dc=com
objectClass: organizationalUnit
ou: people
# Define a user entry for Janet Jones
dn: uid=jjones,ou=people,dc=mycompany,dc=com
objectClass: inetOrgPerson
uid: jjones
sn: jones
cn: janet jones
mail: j.jones@mycompany.com
userPassword: janet
# Define a user entry for Fred Bloggs
dn: uid=fbloggs,ou=people,dc=mycompany,dc=com
objectClass: inetOrgPerson
uid: fbloggs
sn: bloggs
cn: fred bloggs
mail: f.bloggs@mycompany.com
userPassword: fred
# Define an entry to contain LDAP groups
# searches for roles are based on this entry
dn: ou=groups,dc=mycompany,dc=com
objectClass: organizationalUnit
ou: groups
# Define an entry for the "tomcat" role
dn: cn=tomcat,ou=groups,dc=mycompany,dc=com
objectClass: groupOfUniqueNames
cn: tomcat
uniqueMember: uid=jjones,ou=people,dc=mycompany,dc=com
uniqueMember: uid=fbloggs,ou=people,dc=mycompany,dc=com
# Define an entry for the "role1" role
dn: cn=role1,ou=groups,dc=mycompany,dc=com
objectClass: groupOfUniqueNames
cn: role1
uniqueMember: uid=fbloggs,ou=people,dc=mycompany,dc=com
|  |  |  |  |
An example Realm element for the OpenLDAP directory
server configured as described above might look like this, assuming
that users use their uid (e.g. jjones) to login to the
application and that an anonymous connection is sufficient to search
the directory and retrieve role information:
 |  |  |  |
<Realm className="org.apache.catalina.realm.JNDIRealm" debug="99"
connectionURL="ldap://localhost:389"
userPattern="uid={0},ou=people,dc=mycompany,dc=com"
roleBase="ou=groups,dc=mycompany,dc=com"
roleName="cn"
roleSearch="(uniqueMember={0})"
/>
|  |  |  |  |
With this configuration, the realm will determine the user's
distinguished name by substituting the username into the
userPattern, authenticate by binding to the directory
with this DN and the password received from the user, and search the
directory to find the user's roles.
Now suppose that users are expected to enter their email address
rather than their userid when logging in. In this case the realm must
search the directory for the user's entry. (A search is also necessary
when user entries are held in multiple subtrees corresponding perhaps
to different organizational units or company locations).
Further, suppose that in addition to the group entries you want to
use an attribute of the user's entry to hold roles. Now the entry for
Janet Jones might read as follows:
 |  |  |  |
dn: uid=jjones,ou=people,dc=mycompany,dc=com
objectClass: inetOrgPerson
uid: jjones
sn: jones
cn: janet jones
mail: j.jones@mycompany.com
memberOf: role2
memberOf: role3
userPassword: janet
|  |  |  |  |
This realm configuration would satisfy the new requirements:
 |  |  |  |
<Realm className="org.apache.catalina.realm.JNDIRealm" debug="99"
connectionURL="ldap://localhost:389"
userBase="ou=people,dc=mycompany,dc=com"
userSearch="(mail={0})"
userRoleName="memberOf"
roleBase="ou=groups,dc=mycompany,dc=com"
roleName="cn"
roleSearch="(uniqueMember={0})"
/>
|  |  |  |  |
Now when Janet Jones logs in as "j.jones@mycompany.com", the realm
searches the directory for a unique entry with that value as its mail
attribute and attempts to bind to the directory as
uid=jjones,ou=people,dc=mycompany,dc=com with the given
password. If authentication succeeds, she is assigned three roles:
"role2" and "role3", the values of the "memberOf" attribute in her
directory entry, and "tomcat", the value of the "cn" attribute in the
only group entry of which she is a member.
Finally, to authenticate the user by retrieving
the password from the directory and making a local comparison in the
realm, you might use a realm configuration like this:
 |  |  |  |
<Realm className="org.apache.catalina.realm.JNDIRealm" debug="99"
connectionName="cn=Manager,dc=mycompany,dc=com"
connectionPassword="secret"
connectionURL="ldap://localhost:389"
userPassword="userPassword"
userPattern="uid={0},ou=people,dc=mycompany,dc=com"
roleBase="ou=groups,dc=mycompany,dc=com"
roleName="cn"
roleSearch="(uniqueMember={0})"
/>
|  |  |  |  |
However, as discussed above, the default bind mode for
authentication is usually to be preferred.
另外的注意事项
JNDIRealm根据下面的规则进行运作:
- When a user attempts to access a protected resource for the first time,
Tomcat 5 will call the
authenticate() method of this
Realm. Thus, any changes you have made to the directory
(new users, changed passwords or roles, etc.) will be immediately
reflected.
- Once a user has been authenticated, the user (and his or her associated
roles) are cached within Tomcat for the duration of the user's login.
(For FORM-based authentication, that means until the session times out or
is invalidated; for BASIC authentication, that means until the user
closes their browser). The cached user is not saved and
restored across sessions serialisations. Any changes to the directory
information for an already authenticated user will not be
reflected until the next time that user logs on again.
- Administering the information in the directory server
is the responsibility of your own applications. Tomcat does not
provide any built-in capabilities to maintain users and roles.
- 由这个
Realm记录的排错和异常消息被记录在Logger上,这个Logger与周围的Context , Host , 或 Engine 相关联。在默认的情况下,这个相应的Logger会在$CATALINA_HOME/logs 目录里产生一个日志文件。 Host
|
| MemoryRealm |
简介
MemoryRealm is a simple demonstration implementation of the
Tomcat 5 Realm interface. It is not designed for production use.
At startup time, MemoryRealm loads information about all users, and their
corresponding roles, from an XML document (by default, this document is loaded from $CATALINA_HOME/conf/tomcat-users.xml). Changes to the data
in this file are not recognized until Tomcat is restarted.
Realm元素属性
要配置MemoryRealm,你要产生一个<Realm>元素并把它套嵌在$CATALINA_HOME/conf/server.xml 文件里,就如上面所描述那样。下面的这些属性被这一实现(this implementation)所支持:
| 属性 | 描述 |
|---|
className |
The fully qualified Java class name of this Realm implementation.
You MUST specify the value
"org.apache.catalina.realm.MemoryRealm" here.
| debug |
由这个Realm记录到相关的Logger上的排错(debugging)细节标准。数码越高,输出就越详细。如果没指定,那么默认的排错细节标准是零(0) 。
| digest |
用来以非明文形式贮存密码的“文摘”算法,那些被java.security.MessageDigest类里所接受的算法名称的值才是有效的值。更多信息请参见Digested 密码。如果没指定,密码以明文形式贮存。
| pathname |
Absolute or relative (to $CATALINA_HOME) pathname of the XML document
containing our valid usernames, passwords, and roles. See below for more
information on the format of this file. If not specified, the value
conf/tomcat-users.xml is used.
|
User File Format
The users file (by default, conf/tomcat-users.xml must be an
XML document, with a root element <tomcat-users>. Nested
inside the root element will be a <user> element for each
valid user, consisting of the following attributes:
- name - Username this user must log on with.
- password - Password this user must log on with (in
clear text if the
digest attribute was not set on the
<Realm> element, or digested appropriately as
described here otherwise).
- roles - Comma-delimited list of the role names
associated with this user.
例子
The default installation of Tomcat 5 is configured with a MemoryRealm
nested inside the <Engine> element, so that it applies
to all virtual hosts and web applications. The default contents of the
conf/tomcat-users.xml file is:
 |  |  |  |
<tomcat-users>
<user name="tomcat" password="tomcat" roles="tomcat" />
<user name="role1" password="tomcat" roles="role1" />
<user name="both" password="tomcat" roles="tomcat,role1" />
</tomcat-users>
|  |  |  |  |
另外的注意事项
MemoryRealm根据下面的规则进行运作:
- When Tomcat first starts up, it loads all defined users and their
associated information from the users file. Changes to the data in
this file will not be recognized until Tomcat is
restarted.
- When a user attempts to access a protected resource for the first time,
Tomcat 5 will call the
authenticate() method of this
Realm.
- Once a user has been authenticated, the user (and his or her associated
roles) are cached within Tomcat for the duration of the user's login.
(For FORM-based authentication, that means until the session times out or
is invalidated; for BASIC authentication, that means until the user
closes their browser). The cached user is not saved and
restored across sessions serialisations.
- Administering the information in the users file is the responsibility
of your application. Tomcat does not
provide any built-in capabilities to maintain users and roles.
- 由这个
Realm记录的排错和异常消息被记录在Logger上,这个Logger与周围的Context , Host , 或 Engine 相关联。在默认的情况下,这个相应的Logger会在$CATALINA_HOME/logs 目录里产生一个日志文件。 Host
|
| JAASRealm |
简介
JAASRealm is an implementation of the Tomcat
4 Realm interface that authenticates users through the Java
Authentication & Authorization Service (JAAS) framework, a Java
package that is available as an optional package in Java 2 SDK 1.3 and
is fully integrated as of SDK 1.4 .
Using JAASRealm gives the developer the ability to combine
practically any conceivable security realm with Tomcat's CMA.
JAASRealm is prototype for Tomcat of the proposed JAAS-based
J2EE authentication framework for J2EE v1.4, based on the JCP Specification
Request 196 to enhance container-managed security and promote
'pluggable' authentication mechanisms whose implementations would be
container-independent.
Based on the JAAS login module and principal (see javax.security.auth.spi.LoginModule
and javax.security.Principal), you can develop your own
security mechanism or wrap another third-party mechanism for
integration with the CMA as implemented by Tomcat.
快速上手(Quick Start)
要设置好Tomcat来与你自己JAAS login模块一起使用JAASRealm,你必须遵守下面这些步骤:
- Write your own LoginModule, User and Role classes based
on JAAS (see
the
JAAS Authentication Tutorial and
the JAAS Login Module
Developer's Guide) to be managed by the JAAS Login
Context (
javax.security.auth.login.LoginContext)
- Although not specified in JAAS, you should create
seperate classes to distinguish between users and roles, extending
javax.security.Principal,
so that Tomcat can tell which Principals returned from your login
module are users and which are roles (see org.apache.catalina.realm.JAASRealm).
- Place the compiled classes on Tomcat's classpath
- Set up a login.config file for Java (see JAAS
LoginConfig file) and tell Tomcat where to find it by specifying
its location to the JVM, for instance by setting the environment
variable: JAVA_OPTS=-D
JAVA_OPTS=-Djava.security.auth.login.config==$CATALINA_HOME/conf/jaas.config
- Configure your security-constraints in your web.xml for
the resources you want to protect
- Configure the JAASRealm module in your server.xml
- 如果Tomcat 5已经在运行,重新启动它。
Realm元素属性
要象上面第6步那样配置JAASRealm ,你要产生一个<Realm>元素并把它套嵌在<Engine>节点内的$CATALINA_HOME/conf/server.xml 文件里。下面的这些属性被这一实现(this implementation)所支持:
| 属性 | 描述 |
|---|
className |
The fully qualified Java class name of this Realm implementation.
You MUST specify the value
"org.apache.catalina.realm.MemoryRealm" here.
| debug |
由这个Realm记录到相关的Logger上的排错(debugging)细节标准。数码越高,输出就越详细。如果没指定,那么默认的排错细节标准是零(0) 。
| appName |
The name of the realm as configured in your login configuration file
(JAAS LoginConfig).
| userClassNames |
A comma-seperated list of the names of the classes that you have made
for your user Principals.
| roleClassNames |
A comma-seperated list of the names of the classes that you have made
for your role Principals.
|
例子
Here is an example of how your server.xml snippet should look.
 |  |  |  |
<Realm className="org.apache.catalina.realm.JAASRealm"
appName="MyFooRealm"
userClassNames="org.foobar.realm.FooUser"
roleClassNames="org.foobar.realm.FooRole"
debug="99"/>
|  |  |  |  |
It is the responsibility of your login module to create and save User and
Role objects representing Principals for the user
(javax.security.auth.Subject). If your login module doesn't
create a user object but also doesn't throw a login exception, then the
Tomcat CMA will break and you will be left at the
http://localhost:8080/myapp/j_security_check URI or at some other
unspecified location.
The flexibility of the JAAS approach is two-fold:
- you can carry out whatever processing you require behind
the scenes in your own login module.
- you can plug in a completely different LoginModule by changing the configuration
and restarting the server, without any code changes to your application.
另外的注意事项
-
When a user attempts to access a protected resource for
the first time, Tomcat 4 will call the
authenticate()
method of this Realm. Thus, any changes you have made in
the security mechanism directly (new users, changed passwords or
roles, etc.) will be immediately reflected.
- Once a user has been authenticated, the user (and his or
her associated roles) are cached within Tomcat for the duration of
the user's login. (For FORM-based authentication, that means until
the session times out or is invalidated; for BASIC authentication,
that means until the user closes their browser). Any changes to the
security information for an already authenticated user will not
be reflected until the next time that user logs on again.
- Debugging and exception messages logged by this
Realm
will be recorded by the Logger that is associated with our
surrounding Context, Host, or Engine.
By default, the corresponding Logger will create a log file in the $CATALINA_HOME/logs
directory.
|
|
| 普通特性(Common Features) |
| Digested 密码 |
For each of the standard Realm implementations, the
user's password (by default) is stored in clear text. In many
environments, this is undesireable because casual observers of the
authentication data can collect enough information to log on
successfully, and impersonate other users. To avoid this problem, the
standard implementations support the concept of digesting
user passwords. This allows the stored version of the passwords to be
encoded (in a form that is not easily reversible), but that the
Realm implementation can still utilize for
authentication.
When a standard realm authenticates by retrieving the stored
password and comparing it with the value presented by the user, you
can select digested passwords by specifying the digest
attribute on your <Realm> element. The value for
this attribute must be one of the digest algorithms supported by the
java.security.MessageDigest class (SHA, MD2, or MD5).
When you select this option, the contents of the password that is
stored in the Realm must be the cleartext version of the
password, as digested by the specified algorithm.
When the authenticate() method of the Realm is called, the
(cleartext) password specified by the user is itself digested by the same
algorithm, and the result is compared with the value returned by the
Realm. An equal match implies that the cleartext version of the
original password is the same as the one presented by the user, so that this
user should be authorized.
To calculate the digested value of a cleartext password, two convenience
techniques are supported:
- If you are writing an application that needs to calculate digested
passowrds dynamically, call the static
Digest() method of the
org.apache.catalina.realm.RealmBase class, passing the
cleartext password and the digest algorithm name as arguments. This
method will return the digested password.
- If you want to execute a command line utility to calculate the digested
password, simply execute
 |  |  |  |
java org.apache.catalina.realm.RealmBase \
-a {algorithm} {cleartext-password}
|  |  |  |  |
and the digested version of this cleartext password will be returned to
standard output.
To use either of the above techniques, the
$CATALINA_HOME/server/lib/catalina.jar file will need to be
on your class path to make the RealmBase class available.
|
| 管理员程序(Manager Application) |
If you wish to use the Manager Application
to deploy and undeploy applications in a running Tomcat 5 installation, you
MUST add the "manager" role to at least one username in your selected Realm
implementation. This is because the manager web application itself uses a
security constraint that requires role "manager" to access ANY request URI
within that application.
For security reasons, no username in the default Realm (i.e. using
conf/tomcat-users.xml is assigned the "manager" role. Therfore,
no one will be able to utilize the features of this application until the
Tomcat administrator specifically assigns this role to one or more users.
|
|
|