级别: 中级 Helmut K. C. Tessarek (helmut_tessarek@at.ibm.com), 公认的 IT 专家, IBM
2004 年 9 月 09 日 2008 年 3 月 17 日 更新 本文将逐步向您展示在使用 IBM® DB2® Universal Database™(UDB)作为存储用户和组信息的数据库的情况下,如何编译和配置 mod_auth(nz)_ibmdb2 (一个 Apache 身份验证模块)。文中还解释了如何创建和使用生成 DB2 密码的用户定义函数(UDF)。这里给出的用户定义函数与 Apache 的 htpasswd 实用程序中使用的函数兼容。
本文的学习内容包括:
- 编译模块
- 配置和使用模块:新的指令、一个实际的示例和缓存
- 编译 UDF
简介
自从本文第一次发表以来,Apache web 服务器发生了许多变化,这个模块也有变化。Apache 2.2 引入了一种新的身份验证后端提供者方案,所以在 Apache 2.2 及更高版本中改变了模块名称。尽管 Apache 2.2 提供了一个 SQL 数据库 API(称为 DBD 框架),但是使用 mod_authnz_ibmdb2 仍然是有意义的,它允许缓存用户和组信息,不但检验 Apache 使用的散列值,还检验常规的 MD5 散列值和明文密码。在 web 应用程序中,经常使用常规的 “无种子” MD5 散列值。
Apache 1.x 的 mod_auth_ibmdb2 已经停止开发,但是可以在 sourceforge.net 上的 'mod_auth_ibmdb2 (Apache 1.x)' 包中找到用于 Apache 1.x 的最新版本。
在开始之前,需要能够访问 DB2 系统。无论 DB2 与 Apache 安装在同一台机器上,还是把数据库安装在另一台机器上,都没有关系。不过,如果数据库在另一台机器上,则应确保应用程序开发客户机被安装和配置在当前运行 Apache 的那台机器上。要了解有关安装 DB2 的信息,请参阅 Speed-start your Linux app 2003: Installing DB2 Version 8.1。
该模块与 UDF 都是用 C 编写的,只要平台安装了适当的包含文件和库文件,它们就应该能够在所有平台上编译和运行。
本文主要讨论 Linux 平台。该模块是在 Linux 上开发的。
开始之前
从 mod_auth(nz)_ibmdb2 Web 站点下载最新的源代码,到编写本文时最新版本是 mod_authnz_ibmdb2-1.26.tar.gz(Apache 2.2)、mod_auth_ibmdb2-1.10.tar.gz(Apache 2.0)和 db2-auth-udfs-1.3.tar.gz。
编译模块
打开一个终端并以 root 身份登录。接下来,进入一个目录并对 mod_authnz_ibmdb2-1.26.tar.gz 文件进行解压缩(在本例中,将使用目录 /ext)。
[root@atvie01s ext]# tar -xzf mod_authnz_ibmdb2-1.26.tar.gz
[root@atvie01s ext]# cd mod_authnz_ibmdb2
[root@atvie01s mod_authnz_ibmdb2]# ls -l
total 80
-rw-r--r-- 1 tessus tessus 13521 2007-03-21 22:39 caching.h
-rw-r--r-- 1 tessus tessus 778 2008-01-08 05:47 CHANGES
-rw-r--r-- 1 tessus tessus 1514 2008-01-08 05:47 INSTALL
-rwxr-xr-x 1 tessus tessus 940 2007-03-21 06:50 makemod
-rwxr-xr-x 1 tessus tessus 993 2008-01-08 05:16 makemod.bat
drwxr-xr-x 3 tessus tessus 16 2008-01-08 05:49 man
-rw-r--r-- 1 tessus tessus 36003 2008-01-08 03:40 mod_authnz_ibmdb2.c
-rw-r--r-- 1 tessus tessus 4022 2008-01-07 00:44 mod_authnz_ibmdb2.h
-rw-r--r-- 1 tessus tessus 4218 2008-01-08 05:47 README
|
在这个目录中,可以发现一个 makemod 脚本,我们将使用该脚本构建用于 Apache 的模块(共享对象)。为此,必须检查该脚本中的一些参数。使用您喜欢的编辑器将以下参数修改成适合您环境的值。
DB2PATH=/home/db2inst1/sqllib
APXS=/usr/local/apache/bin/apxs
将 DB2PATH 设置为访问 DB2 UDB 的那个目录。该目录通常是实例的主目录。将 APXS 设置为 apxs 二进制代码的路径。apxs 二进制代码通常安装在 /<your apache home>/bin 目录中。
修改上述设置以后,运行以下脚本:
[root@atvie01s mod_authnz_ibmdb2]# ./makemod
|
接下来,将下面这行代码添加到 httpd.conf 中:
Apache 2.2 及更高版本:
LoadModule authnz_ibmdb2_module modules/mod_authnz_ibmdb2.so
|
Apache 2.0.x 和 Apache 1.3.x:
LoadModule ibmdb2_auth_module modules/mod_auth_ibmdb2.so
|
在使用 Apache 1.3.x 时,可能还需要添加以下代码:
AddModule mod_auth_ibmdb2.c
|
如果找不到 sqlcli1.h 头文件或 DB2 库 libdb2.so,那么很可能是因为没有正确地设置 DB2PATH。在这种情况下,应该在系统中搜索上面提到的两个文件。
配置和使用模块
新的指令
随模块一起出现的,还有几个新的指令,Apache 可以用这些指令控制身份验证过程的行为。下面是这些新指令的列表,以及它们的默认值和对它们的描述。
表 1. 指令列表
指令
|
默认值
|
描述
|
|
|
| | AuthIBMDB2User |
| 用于连接 DB2 数据库的用户
| | AuthIBMDB2Password |
| 用于连接 DB2 数据库的密码
| AuthIBMDB2Database
|
| 数据库名
| AuthIBMDB2UserTable
|
| 用户表的名称。如果该名称不是完全限定的,则使用连接数据库的用户作为模式名。
| AuthIBMDB2GroupTable
|
| 组表的名称。如果该名称不是完全限定的,则使用连接数据库的用户作为模式名。 | AuthIBMDB2NameField
| username
| 用户表和组表中表示用户名列的列名
| AuthIBMDB2GroupField
| groupname
| 组表中表示组名列的列名 | AuthIBMDB2PasswordField
| password
| 用户表中表示密码列的列名 | AuthIBMDB2CryptedPasswords
| on
| 如果 AuthIBMDB2CryptedPasswords 为 “On”,那么密码是加密存储的。这里不必指定使用哪一种加密。有效的加密方法有:normal md5 hash(在 php 中是 32 个字符)、seeded md5 value(用 Apache 的 htpasswd 实用程序生成,或者在 /etc/shadow 目录中)和 crypt。如果 AuthIBMDB2CryptedPasswords 设置为 “Off”,则使用明文密码。要了解有关在 DB2 内生成密码的知识,请参阅本文中的 UDF 一节。
| AuthIBMDB2KeepAlive
| on
| 如果 AuthIBMDB2KeepAlive 为 “On”,则服务器实例将使 IBM DB2 服务器连接保持开放状态。
| AuthIBMDB2Authoritative
| on
| 如果 AuthIBMDB2Authoritative 为 “Off”,当在数据库中没有发现用户时,则让其他身份验证模块尝试寻找用户。
| AuthIBMDB2NoPasswd
| off
| 如果 AuthIBMDB2NoPasswd 为 “On”,那么只要用户在数据库中,该用户输入的任何密码都将被接受。
| AuthIBMDB2UserCondition
|
| 可以用来限制对用户表的查询。该值应该是一个字符串,在查询表时,希望将该字符串添加到 where 子句的后面。例如,如果用户表有一个 “active” 字段,并希望只有在该字段为 1 时用户才能登录,那么可以使用以下指令:AuthIBMDB2UserCondition active=1。
| AuthIBMDB2GroupCondition
|
| 可以用来限制对组表的查询。该值应该是一个字符串,在查询表时,希望将该字符串添加到 where 子句的后面。例如,如果组表有一个 “active” 字段,并且希望只有在该字段为 1 时用户才能登录,那么可以使用以下指令:AuthIBMDB2GroupCondition active=1。 | AuthIBMDB2UserProc
|
| 用于用户身份验证的存储过程的名称
| AuthIBMDB2GroupProc
|
| 用于组身份验证的存储过程的名称
| AuthIBMDB2Caching
| off
| 如果 AuthIBMDB2Caching 为 “On”,那么用户凭证将缓存在一个文件中。
| AuthIBMDB2GroupCaching
| off
| 如果 AuthIBMDB2GroupCaching 为 “On”,那么组信息将缓存在一个文件中。
| AuthIBMDB2CacheFile
| /tmp/auth_cred_cache
| 定义缓存文件的位置和名称。
| AuthIBMDB2CacheLifetime
| 300
| 设置缓存元素的超时时间,以秒为单位。
|
一个实际示例
在这个示例中,我们将使用 /var/www 作为 Web 根目录,使用 /data/private 作为 /private 别名。要连接到数据库,需要输入用户名 tessarek 和密码 helmut。数据库名为 auth。
假设需要使用新安装的 mod_auth(nz)_ibmdb2 模块保护 Web 位置 http://yourserver/private。
首先,需要在 DB2 UDB 中创建用于存储用户和组的两个表。
db2 => connect to auth user tessarek using helmut
Database Connection Information
Database server = DB2/LINUX 9.5.0
SQL authorization ID = TESSAREK
Local database alias = AUTH
db2 => CREATE TABLE USERS ( USERNAME VARCHAR(40) NOT NULL, PASSWORD VARCHAR(40) )
db2 => ALTER TABLE USERS ADD PRIMARY KEY (USERNAME)
db2 => CREATE TABLE GROUPS ( USERNAME VARCHAR(40) NOT NULL, GROUPNAME VARCHAR(40) NOT NULL )
db2 => ALTER TABLE GROUPS ADD PRIMARY KEY (USERNAME,GROUPNAME)
|
不一定要像上面示例那样创建这两个表。它们可以是视图,也可以有其他的列。要考虑的要点是,用户表中必须有表示用户名和密码的列,并且用户名列必须是惟一的。另外,在组表中必须有表示用户名和组名的列,用户名和组名列都必须是惟一的。可以选择自己喜欢的任何名称作为用户名、组名和密码列的列名。
接下来,需要在新创建的表中插入用户和组信息。如果不想做以下任何事情:
- 使用明文密码
- 使用 Apache 的 htpasswd 创建一个新的加密口令
- 从现有的用户文件中复制加密的口令
那么,必须像下一节描述的那样 安装 UDF。
db2 => insert into users (username,password) values ('test', apr_md5('testpwd'))
db2 => insert into groups (username,groupname) values ('test','admin')
db2 => select * from users
USERNAME PASSWORD
---------------------------------------- ----------------------------------------
test $apr1$bZGrA...$Ic7E68bhwdDnpX6XG/w8i/
1 record(s) selected.
db2 => select * from groups
USERNAME GROUPNAME
---------------------------------------- ----------------------------------------
test admin
1 record(s) selected.
|
注意:apr_md5 是一个用户定义函数,本文的 UDF 一节中对该函数进行了解释。
最后,还要编辑 httpd.conf 文件并添加下面几行代码。要使更改生效,必须重新启动 Web 服务器。
Alias /private "/data/private/"
<Directory "/data/private">
AuthName "DB2 Authentication for private"
AuthType Basic
AuthBasicProvider ibmdb2 # Apache >= 2.2.x only
AuthIBMDB2User tessarek
AuthIBMDB2Password helmut
AuthIBMDB2Database auth
AuthIBMDB2UserTable users
AuthIBMDB2NameField username
AuthIBMDB2PasswordField password
AuthIBMDB2CryptedPasswords On
AuthIBMDB2KeepAlive On
AuthIBMDB2Authoritative On
AuthIBMDB2NoPasswd Off
AuthIBMDB2GroupTable groups
AuthIBMDB2GroupField groupname
require group admin
AllowOverride None
</Directory>
|
也可以忽略参数 AuthIBMDB2NameField、AuthIBMDB2PasswordField、AuthIBMDB2CryptedPasswords、AuthIBMDB2KeepAlive、AuthIBMDB2Authoritative 和 AuthIBMDB2NoPasswd,因为我们将使用默认值。
如果在声明这些表时没有使用模式名,则用来连接数据库的用户名将被用作模式名。
将 Web 浏览器指向 http://yourserver/private 并查看结果。如果一切正常,那么应该可以看到如图 1 所示的情况。
图 1. 受保护的区域
缓存
对于有大量请求的站点,通过缓存用户凭证来减少数据库请求的做法很有意义。在默认情况下,缓存功能是禁用的,所以必须用指令 AuthIBMDB2Caching On 和 AuthIBMDB2GroupCaching On 启用缓存。缓存文件是在 /tmp 文件系统中创建的,因为通常每个人都拥有对该文件系统的写访问权限。可以通过 AuthIBMDB2CacheFile 修改指向缓存文件的路径。可以通过 AuthIBMDB2CacheLifetime 设置用户凭证在缓存文件中的生存期。在默认情况下,该生存期被设置为 300 秒(5 分钟)。
如果想使用 RAM 中的缓存,那么可以创建一个 RAM 盘并将 AuthIBMDB2CacheFile 指向新的文件系统。要确保用来运行 Apache 的用户对这个文件系统有读写访问权。
可以使用下面的命令在 Linux 中创建一个 RAM 盘(该 RAM 盘的大小为 5 MB):
mount -t tmpfs -o size=5M,nr_inodes=2k,mode=770 tmpfs /mnt/ramfs
|
存储过程
这个模块支持通过存储过程从数据库中获取用户和组信息。使用存储过程的原因包括管理简单和性能较好。存储过程必须符合一种特定的参数格式。
用于用户身份验证的存储过程有一个输入参数(用户名)和一个输出值(此用户的密码):
PROCEDURE user_procedure_name ( IN VARCHAR, OUT VARCHAR )
用于组身份验证的存储过程有一个输入参数(用户),它必须返回结果集的游标:
PROCEDURE group_procedure_name ( IN VARCHAR )
下面是两个存储过程,它们操作 实际示例 中的表。
文件 1: sp.sql
CREATE PROCEDURE user_sp (IN v_username VARCHAR(40), OUT v_password VARCHAR(40))
LANGUAGE SQL
BEGIN
SELECT password INTO v_password FROM users WHERE username = v_username;
END@
CREATE PROCEDURE group_sp (IN v_username VARCHAR(40))
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
DECLARE res CURSOR WITH RETURN FOR
SELECT groupname FROM groups WHERE username = v_username;
OPEN res;
END@
|
可以作为实例用户运行以下命令,从而安装这两个存储过程:
[db2inst1@atvie01s ~]$ db2 connect to auth user tessarek using helmut
[db2inst1@atvie01s ~]$ db2 -td@ -f sp.sql
|
如果要使用存储过程,那么必须编辑 httpd.conf 文件并重新启动 Web 服务器。
Alias /private "/data/private/"
<Directory "/data/private">
AuthName "DB2 Authentication for private"
AuthType Basic
AuthBasicProvider ibmdb2 # Apache >= 2.2.x only
AuthIBMDB2User tessarek
AuthIBMDB2Password helmut
AuthIBMDB2Database auth
AuthIBMDB2UserProc user_sp
AuthIBMDB2GroupProc group_sp
require group admin
AllowOverride None
</Directory>
|
编译 UDF
打开一个终端并以 DB2 UDB 实例用户的身份登录。然后进入解压 db2-auth-udfs-1.3.tar.gz 的目录(在本例中,将使用目录 /ext)。
[db2inst1@atvie01s ~]$ cd /ext
[db2inst1@atvie01s ext]$ tar -xzf db2-auth-udfs-1.3.tar.gz
[db2inst1@atvie01s ext]$ db2-auth-udfs
[db2inst1@atvie01s db2-auth-udfs]$ ls -l
total 56
-rw-rw-r-- 1 db2inst1 db2grp1 596 2008-01-04 09:03 CHANGES
-rw-rw-r-- 1 db2inst1 db2grp1 102 2006-02-17 11:03 drop_udfs.ddl
-rw-rw-r-- 1 db2inst1 db2grp1 4407 2008-01-04 08:58 hash.c
-rw-rw-r-- 1 db2inst1 db2grp1 55 2007-03-06 03:52 hash.def
-rw-rw-r-- 1 db2inst1 db2grp1 3550 2007-02-27 03:36 hash.h
-rw-rw-r-- 1 db2inst1 db2grp1 892 2007-03-06 03:52 INSTALL
-rwxrwxr-x 1 db2inst1 db2grp1 740 2007-03-06 03:52 maketest
-rw-rw-r-- 1 db2inst1 db2grp1 377 2007-03-06 03:45 maketest.bat
-rwxrwxr-x 1 db2inst1 db2grp1 1218 2007-03-27 18:27 makeudf
-rw-rw-r-- 1 db2inst1 db2grp1 532 2007-03-06 03:45 makeudf.bat
-rw-rw-r-- 1 db2inst1 db2grp1 1131 2007-03-06 03:52 README
-rw-rw-r-- 1 db2inst1 db2grp1 1020 2008-01-04 08:57 reg_udfs.ddl
-rw-rw-r-- 1 db2inst1 db2grp1 595 2007-02-27 03:40 test_hash.c
|
在这个目录中可以发现一个 makeudf 脚本,我们将用该脚本构建 UDF。为此,必须修改脚本中的参数。使用编辑器将下面的参数改为适合您环境的值。
DB2PATH=/home/db2inst1/sqllib
将 DB2PATH 设置为访问 DB2 的那个目录。该目录通常是实例的主目录。
修改了上述参数之后,运行脚本:
[db2inst1@atvie01s db2-auth-udfs]$ ./makeudf
|
要注册这些 UDF,需要连接到数据库并运行以下脚本:
[db2inst1@atvie01s db2-auth-udfs]$ db2 connect to auth user tessarek using helmut
Database Connection Information
Database server = DB2/LINUX 9.5.0
SQL authorization ID = TESSAREK
Local database alias = AUTH
[db2inst1@atvie01s db2-auth-udfs]$ db2 -tvf reg_udfs.ddl
CREATE FUNCTION md5(VARCHAR(120))
RETURNS VARCHAR(32)
NOT FENCED
DETERMINISTIC
NO SQL
NO EXTERNAL ACTION
LANGUAGE C
RETURNS NULL ON NULL INPUT
PARAMETER STYLE SQL
EXTERNAL NAME 'hash!md5'
DB20000I The SQL command completed successfully.
CREATE FUNCTION apr_md5(VARCHAR(120))
RETURNS VARCHAR(37)
NOT FENCED
NO SQL
NO EXTERNAL ACTION
LANGUAGE C
RETURNS NULL ON NULL INPUT
PARAMETER STYLE SQL
EXTERNAL NAME 'hash!aprmd5'
DB20000I The SQL command completed successfully.
CREATE FUNCTION apr_crypt(VARCHAR(120))
RETURNS VARCHAR(13)
NOT FENCED
NO SQL
NO EXTERNAL ACTION
LANGUAGE C
RETURNS NULL ON NULL INPUT
PARAMETER STYLE SQL
EXTERNAL NAME 'hash!aprcrypt'
DB20000I The SQL command completed successfully.
CREATE FUNCTION apr_sha1(VARCHAR(120))
RETURNS VARCHAR(33)
NOT FENCED
DETERMINISTIC
NO SQL
NO EXTERNAL ACTION
LANGUAGE C
RETURNS NULL ON NULL INPUT
PARAMETER STYLE SQL
EXTERNAL NAME 'hash!aprsha1'
DB20000I The SQL command completed successfully.
[db2inst1@atvie01s db2-auth-udfs]$ db2 connect reset
|
这些 UDF 是用 ANSI C 编写的并使用 APR 库。它们应该能够在所有平台上编译和运行。可以使用 sqllib/samples/c 目录中的 bldrtn 脚本作为起点,也可以修改 makeudf 脚本。
对 UDF 的描述
下面是 UDF 的列表、示例输出以及相关的描述。
表 2. UDF 的列表
UDF 名称
|
示例输出
|
描述
|
|
|
| | md5 | 342df5b036b2f28184536820af6d1caf | MD5 散列值。这个 MD5 函数与 PHP MD5 函数兼容。 | | apr_md5 | $apr1$bhX6Z/..$kAxtFQozYsZhgNgqVnJd0. | 有种子的 MD5 散列值。apr_md5 与在 htpasswd 实用程序中使用的 Apache 函数兼容。 | | apr_crypt | bhqWHYBAJAQ2w | UNIX® crypt。apr_crypt 与在 htpasswd 实用程序中使用的 Apache 函数兼容。 | | apr_sha1 | {SHA}mO8HWOaqxvmp4Rl1SMgZC3LJWB0= | SHA1 算法。apr_sha1 与在 htpasswd 实用程序中使用的 Apache 函数兼容。 |
调试
如果在 httpd.conf 文件中设置 LogLevel debug,那么将得到关于在身份验证过程中发生的情况的详细信息。下面是在运行 实际示例 期间生成的调试文本的两个示例。
示例 1. 在禁用缓存的情况下调试身份验证过程
[notice] Apache/2.2.6 (Unix) mod_ssl/2.2.6 PHP/5.2.5 mod_authnz_ibmdb2/1.26 configured --
resuming normal operations
[info] Server built: Sep 8 2007 11:57:34
[debug] prefork.c(991): AcceptMutex: sysvsem (default: sysvsem)
[debug] mod_authnz_ibmdb2.c(1134): begin authenticate for user=[test], uri=[/private/]
[debug] mod_authnz_ibmdb2.c(523): begin get_ibmdb2_pw()
[debug] mod_authnz_ibmdb2.c(232): DB connection is dead or nonexistent;
create connection
[debug] mod_authnz_ibmdb2.c(235): allocate an environment handle
[debug] mod_authnz_ibmdb2.c(690): query=[SELECT rtrim(password) FROM users
WHERE username='test']
[debug] mod_authnz_ibmdb2.c(692): allocate a statement handle
[debug] mod_authnz_ibmdb2.c(698): prepare the statement
[debug] mod_authnz_ibmdb2.c(715): execute the statement
[debug] mod_authnz_ibmdb2.c(772): fetch each row, and display
[debug] mod_authnz_ibmdb2.c(788): get data from query resultset
[debug] mod_authnz_ibmdb2.c(795): password from database=
[$apr1$bZGrA...$Ic7E68bhwdDnpX6XG/w8i/]
[debug] mod_authnz_ibmdb2.c(797): call SQLFetch() (point to next row)
[debug] mod_authnz_ibmdb2.c(803): free statement handle
[debug] mod_authnz_ibmdb2.c(309): keepalive on; do not disconnect from database
[debug] mod_authnz_ibmdb2.c(813): end get_ibmdb2_pw()
[debug] mod_authnz_ibmdb2.c(877): begin get_ibmdb2_groups()
[debug] mod_authnz_ibmdb2.c(227): DB connection is alive; re-using
[debug] mod_authnz_ibmdb2.c(913): query=[SELECT rtrim(groupname) FROM groups
WHERE username='test']
[debug] mod_authnz_ibmdb2.c(915): allocate a statement handle
[debug] mod_authnz_ibmdb2.c(921): prepare the statement
[debug] mod_authnz_ibmdb2.c(938): execute the statement
[debug] mod_authnz_ibmdb2.c(1010): fetch each row, and display
[debug] mod_authnz_ibmdb2.c(1035): get data from query resultset
[debug] mod_authnz_ibmdb2.c(1050): group #1 from database=[admin]
[debug] mod_authnz_ibmdb2.c(1052): call SQLFetch() (point to next row)
[debug] mod_authnz_ibmdb2.c(1058): free statement handle
[debug] mod_authnz_ibmdb2.c(309): keepalive on; do not disconnect from database
[debug] mod_authnz_ibmdb2.c(1068): end get_ibmdb2_groups()
|
示例 2. 在启用缓存的情况下调试身份验证过程
[notice] Apache/2.2.6 (Unix) mod_ssl/2.2.6 PHP/5.2.5 mod_authnz_ibmdb2/1.26 configured --
resuming normal operations
[info] Server built: Sep 8 2007 11:57:34
[debug] prefork.c(991): AcceptMutex: sysvsem (default: sysvsem)
[debug] mod_authnz_ibmdb2.c(1134): begin authenticate for user=[test], uri=[/private/]
[debug] caching.h(211): user [test] - [$apr1$bZGrA...$Ic7E68bhwdDnpX6XG/w8i/]
found in cache
[debug] caching.h(502): groups for user [test] found in cache
|
二进制版本
尽管有在 Windows 上构建模块和 UDF 的脚本,但是大多数 Windows 用户没有安装编译所需的开发环境。
可以从 mod_auth(nz)_ibmdb2 网站的 binary releases 包部分下载用于 32 位 Windows 的最新二进制代码。
参考资料 学习
获得产品和技术
- 下载本文使用的 mod_authnz_ibmdb2 的 源代码。
- 下载 mod_auth_ibmdb2 的 源代码。
- 下载本文使用的 UDF 的 源代码。
- 下载 PDF 文件格式的 文档。
- 下载用于 32 位 Windows 的 二进制代码。
-
使用
IBM 试用软件 构建您的下一个开发项目,这些软件可以从 developerWorks 直接下载。
讨论
关于作者  | 
|  | Helmut K. C. Tessarek 在 IBM 奥地利的 Software Group Services 中担任一名 IBM DB2 专家,专门从事 DB2 Universal Database (性能和调优以及 DB2 Universal Database 数据复制)的研究。他是 mod_auth_ibmdb2 的作者。您可以通过
helmut_tessarek@at.ibm.com与 Helmut 联系。
|
对本文的评价
|