我正在将 apache mod_auth_form 从 2.0.5 升级到 2.4。配置 mod_session_dbd 时遇到问题。需要帮忙!!
我的 httpd.conf 配置 - 即使在用户通过 login.php 进行身份验证后,也无法重定向到 protected main/main.php 页面。
代码:
CREATE TABLE `session` (
`id` bigint unsigned NOT NULL auto_increment,
`value` varchar(512) NOT NULL DEFAULT '',
`expiry` bigint unsigned NOT NULL DEFAULT 0,
`key` varchar(256) NOT NULL DEFAULT '',
primary key (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
DBDriver mysql
DBDParams "host=127.0.0.1 port=3306 dbname=aware_db user=apache pass=dhishkhk"
DBDMin 4
DBDKeep 8
DBDMax 20
DBDExptime 300
DBDPrepareSQL "select value from session where `key` = %s and (expiry = 0 or expiry > %lld)" selectsession
DBDPrepareSQL "delete from session where `key` = %s" deletesession
DBDPrepareSQL "insert into session (value, expiry, `key`) values (%s, %lld, %s)" insertsession
DBDPrepareSQL "update session set value = %s, expiry = %lld, `key` = %s where `key` = %s" updatesession
<Directory "/var/www/html/main">
Options -Indexes +FollowSymLinks
SSLRequireSSL
SetHandler form-login-handler
AuthFormLoginRequiredLocation /login.php
AuthFormLoginSuccessLocation /main/main.php
AuthFormProvider dbd
AuthFormUsername uid
AuthFormPassword password
AuthType form
AuthName "My Login"
ErrorDocument 401 /login.php
Session On
#SessionDBDPerUser On
SessionDBDCookieName session path=/;
SessionDBDSelectLabel selectsession
SessionDBDDeleteLabel deletesession
SessionDBDInsertLabel insertsession
SessionDBDUpdateLabel updatesession
SessionDBDCookieRemove Off
Require valid-user
ExpiresActive On
ExpiresByType application/x-java-jnlp-file "now"
</Directory>
我们编写自定义的login.php 脚本,该脚本在客户端首次访问主页时调用。该脚本显示一个登录 HTML 表单,然后采用用户输入(uid 和密码)来针对 SQL 用户数据库以及 LDAP 用户帐户进行身份验证。一旦 uid/密码通过身份验证,mod_session 似乎能够设置“ session ”cookie,但无法将 session 存储到我创建的“ session ”表中。我的理解是 mod_session_dbd 会将 cookie 中的“ session ”与 session 数据库表中的信息进行匹配(通过 selectsession DBDPrepareSQL),并查看用户已经经过身份验证,并让它进入主页,而不是登录。再次检查 php 就好像它没有经过身份验证(这就是我上面的配置所发生的情况)。
mod_session_dbd 的 apache 文档很少且不完整,而且我无法在网络上的任何地方找到可供引用的 mod_session_dbd 的任何工作示例。甚至不知道如何调试 mod_session_dbd (LogLevel 设置似乎没有得到痕迹)...任何帮助/建议将不胜感激!!
最佳答案
我认为这里的问题是您的外部登录脚本不是 mod_auth_form 的“身份验证提供程序”,无法直接与 mod_auth_form 通信身份验证已成功。 (只有在此之后 session 才会被插入到数据库中)。然而,这种通信可以间接完成。继续阅读...
我也有类似的设置。我最终做的是让我的外部登录脚本模仿 mod_session_dbd 并在成功身份验证后自行插入数据库条目。之后,再次将页面重定向到同一保护区。使用类似的东西(这是 PHP 代码)
header("Location: $toURL");
为了 mod_session_dbd 的目的,您的 session 表必须至少有三列:uuid、session 和 expiry。 (但是 session 表也将兼作 mod_authn_dbd 的 session 密码表。请参阅下面的讨论。)
mod_auth_form 会在 cookie 中为您生成 uuid,只要您有以下指令。您的脚本可以从 cookie 中读取值(例如,从您的 PHP 脚本中)
SessionDBDCookieName uuid
mod_auth_form 期望 session 具有三个键值对,如下所示:
Realm-user=foo&Realm-pw=bar&expiry=1453231822000000
(过期时间是自 Epoch 以来的微秒数:即 unix 时间乘以 1,000,000)
上面还假设您已将 AuthName 配置为“Realm”
AuthName "Realm"
现在,虽然登录脚本无法将成功的身份验证结果传达给 mod_auth_form,但它可以通过将 uuid 的 cookie 与 session 表的匹配行来间接实现此目的。
接下来,我将 mod_auth_form 配置为使用 mod_authn_dbd 作为“身份验证提供程序”。然而,后者并不进行真正的身份验证(登录脚本已经完成了身份验证)。相反,它只是检查请求中是否存在 session (uuid 的 cookie 与 session 表中的匹配行)。
因此,我所做的就是向 session 表中再添加一列(称为“session_pw”),然后配置 mod_authn_dbd 以使用以下查询进行密码查找(我使用的是 MySQL):
AuthFormProvider dbd
AuthDBDUserPWQuery "SELECT session_pw FROM web_sessions WHERE uuid = %s and expiry>unix_timestamp()*1000000"
关键是要知道 mod_authn_dbd 期望什么,而这并没有很好的记录 - 它期望上述查询中的密码 (session_pw) 值已通过 Apache 允许的格式之一加密(请参阅 this )。就我而言,我决定使用 crypt,因此在 session 表中,我的登录脚本实际上为 session_pw 插入以下值
convert(encrypt(?, 'Cm') using ascii)
哪里?绑定(bind)到我生成的 session 密码(只是一个随机数)——这个相同的值也必须放入上面显示的 session 值中(即替换“Realm-”的键值对的占位符“bar”)密码”)。
一旦mod_authn_dbd发现密码匹配,它会让mod_auth_form知道,后者会让请求进入保护区。 (所以这里我所做的是使用密码检查来测试 session 是否存在)
我需要的另一个技巧是禁用 session 插入并更新 mod_session_dbd 的查询(因为我的登录脚本现在执行插入)。我通过以下两个指令做到了这一点:
# we disable session insertion by mod_auth_form/mod_session_dbd -- login.php will insert the session
DBDPrepareSQL "select %s, %lld, %s" insertsession
# we disable session update by mod_auth_form/mod_session_dbd
DBDPrepareSQL "select %s, %lld, %s, %s" updatesession
最后,我想我可以分享我的 session 表的架构,以防万一这可以帮助某人:
CREATE TABLE `web_sessions` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`u_name` varchar(31) NOT NULL, -- used for debugging only
`session_pw` varchar(256) NOT NULL, -- encrypte by convert(encrypt(?, 'Cm') using ascii)
`session` varchar(256) NOT NULL, -- mod_session_dbd's value
`expiry` bigint NOT NULL, -- mod_session_dbd's expiry: microsecs since Epoch
`uuid` varchar(256) NOT NULL, -- mod_session_dbd's key: uuid
UNIQUE KEY `id` (`id`),
UNIQUE KEY `uuid` (`uuid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
希望这有帮助!
关于Apache mod_session_dbd - 有人让它工作吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34755791/