The Jakarta Project
      The Apache Jakarta Tomcat Servlet/JSP Container

链接

用户指南

参考

开发 Tomcat

The Apache Jakarta Tomcat 5 Servlet/JSP Container

Realm Configuration HOW-TO

Printer Friendly Version
print-friendly
版本
目录

快速上手(Quick Start)

什么是Realm? (What is a Realm?)
配置一个Realm (Configuring a Realm)
标准Realm实现(Standard Realm Implementations)
JDBCRealm
DataSourceRealm
JNDIRealm
MemoryRealm
JAASRealm
普通特性(Common Features)
Digested 密码
应用程序示例(Example Application)
管理员程序(Manager Application)

快速上手(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 (Configuring a Realm)

在进入详细的标准Realm实现之前,弄懂怎样配置一个Realm是很重要的。通常,你需要把一个XML元素加入到你的conf/server.xml配置文件中,它看起来象这样:

<Realm className="... class name for this implementation" 
... other attributes for this implementation .../>

<Realm> 元素可以被套嵌(nested)在下面三个不同元素中的认何一个当中,它对于这个Realm的“作用域”("scope")有直接影响(例如,哪些网络程序可以共享相同的认证信息)。

  • 在<Engine> 元素里边 - 这个Realm将会被所有虚拟主机上的所有网络程序共享,除非它被嵌套在下级<Host> 或<Context>元素里的Realm元素覆盖。
  • 在<Host>元素里边 - 这个Realm将会被THIS虚拟主机上所有的网络程序所共享,除非它被嵌套在下级<Context>元素里的Realm元素覆盖。
  • 在<Context>元素里边 - 这个Realm只被THIS网络程序使用。
标准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,你必须遵守下面这些步骤:

  1. 根据上面所描述的规定,在你的数据库里产生表格(tables)和列(columns)。
  2. 配置一个可供Tomcat使用的用户名称和密码,它至少应该有只读(read only)权限来访问上述表格。(Tomcat从不会试图去改写这些表格)。
  3. 把你将要使用的JDBC驱动复制件放置到$CATALINA_HOME/server/lib目录(如果你不想让网络程序使用它的话)或者放在$CATALINA_HOME/common/lib(如果Tomcat 5你的程序都要使用它的话)。注意,唯一只有JAR文件才能被识别。
  4. 象下面所描述的那样,在你的$CATALINA_HOME/conf/server.xml文件设置一个<Realm>元素。
  5. 如果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

表名,它的每一行包含指派给某一特定用户名称的一个角色。这个表格必须至少包括那些由userNameColroleNameCol属性定名的列。

userTable

表名,它的每一行包含一个可被Tomcat识别的用户名称。这个表格必须至少包括那些由userNameColuserCredCol 属性定名的列。

例子

一个用于产生所需表格的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&amp;password=dbpass" 
userTable="users" userNameCol="user_name" userCredCol="user_pass" 
userRoleTable="user_roles" roleNameCol="role_name"/>

另外的注意事项

JDBCRealm根据下面的规则进行运作:

  • 当一个用户第一次试图访问被保护的资源时,Tomcat 5会传叫(call)这个Realmauthenticate()方法。因此,你对于这个数据库所做的认何直接更改(新用户,更改过的密码和角色等等)都会被立即反映出来。
  • 一但用户被认证,用户(以及其相关角色)在这个用户登录期间会被高速缓存(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,你必须遵守下面这些步骤:

  1. 根据上面所描述的规定,在你的数据库里产生表格(tables)和列(columns)。
  2. 配置一个可供Tomcat使用的用户名称和密码,它至少应该有只读(read only)权限来访问上述表格。(Tomcat从不会试图去改写这些表格)。
  3. 为你的数据库配置一个叫做JDBC DataSource的JNDI。关于怎样配置一个叫做JDBC DataSource的JNDI的信息请参看JNDI DataSource Example HOW-TO
  4. 象下面所描述的那样,在你的$CATALINA_HOME/conf/server.xml文件设置一个<Realm>元素。
  5. 如果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

表名,它的每一行包含指派给某一特定用户名称的一个角色。这个表格必须至少包括那些由userNameColroleNameCol属性定名的列。

userTable

表名,它的每一行包含一个可被Tomcat识别的用户名称。这个表格必须至少包括那些由userNameColuserCredCol 属性定名的列。

例子

一个用于产生所需表格的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)这个Realmauthenticate()方法。因此,你对于这个数据库所做的认何直接更改(新用户,更改过的密码和角色等等)都会被立即反映出来。
  • 一但用户被认证,用户(以及其相关角色)在这个用户登录期间会被高速缓存(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就通过connectionNameconnectionPassword 属性指定的用户名称和密码来向这个目录认证它自己。如果属性没有被指定,连接就是无名的。在许多情形下,这也足够了。

选择用户的目录进入

每一个能被认证的用户必须在目录里由一个单个登录(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.
  • Roles as an attribute of the user entry

    Role names may also be held as the values of an attribute in the user's directory entry. Use userRoleName to specify the name of this attribute.

A combination of both approaches to role representation may be used.

快速上手(Quick Start)

要设置好Tomcat来使用JNDIRealm,你必须遵守下面这些步骤:

  1. 确保你的目录服务器是依据上面的要求配置的。
  2. 如果需要,配置一个可供Tomcat使用的用户名称和密码,它应该有只读(read only)权限来访问上述表格。(Tomcat从不会试图去改写这些表格)。
  3. 把你将要使用的JNDI驱动(通常ldap.jar available with JNDI)复制件放置到$CATALINA_HOME/server/lib目录(如果你不想让网络程序使用它的话)或者放在$CATALINA_HOME/common/lib(如果Tomcat 5你的程序都要使用它的话)。
  4. 象下面所描述的那样,在你的$CATALINA_HOME/conf/server.xml文件设置一个<Realm>元素。
  5. 如果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,你必须遵守下面这些步骤:

  1. 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)
  2. 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).
  3. Place the compiled classes on Tomcat's classpath
  4. 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=-DJAVA_OPTS=-Djava.security.auth.login.config==$CATALINA_HOME/conf/jaas.config
  5. Configure your security-constraints in your web.xml for the resources you want to protect
  6. Configure the JAASRealm module in your server.xml
  7. 如果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.

应用程序示例(Example Application)

The example application shipped with Tomcat 5 includes an area that is protected by a security constraint, utilizing form-based login. To access it, point your browser at http://localhost:8080/jsp-examples/security/protected/ and log on with one of the usernames and passwords described for the default MemoryRealm.

管理员程序(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.


Copyright © 1999-2003, Apache Software Foundation