Gallery:模块:httpauth
描述[ ]
使用HTTP认证进行登入。
特点[ ]
- 直接支持HTTP基本认证,使用认证请求头和WWW-认证应答头。
- 支持web服务器认证,使用环境变量REMOTE_USER。
服务器认证[ ]
要使用Kerberos作为服务器认证机制的话,请在你的.htaccess文件中添加:
<Location /gallery2> AuthType Kerberos Require valid-user </Location>
并在site admin -> HTTP Auth中配置HTTP Auth模块,使其使用服务器认证。
登出[ ]
因为大部分的web浏览器会缓存HTTP认证凭证,所以当使用HTTP认证登入后,Gallery登出链接无法按预期地运作。Gallery能够正确地让活动用户登出,但web浏览器会按下一个请求而重新登入。
要解决此问题,HTTP认证应听取Gallery::Logout事件,必要时委任给httpauth.TryLogout页面:http://gallery.svn.sourceforge.net/viewvc/gallery/trunk/gallery2/modules/httpauth/TryLogout.inc?view=markup
TryLogout页面使用下面的方法尝试清除浏览器认证缓存:
- 请求浏览器使用bogus authtype进行认证:
GalleryUtilities::setResponseHeader('HTTP/1.0 401 Unauthorized', false); GalleryUtilities::setResponseHeader('WWW-Authenticate: Bogus', false);
- 使用随机用户名和密码进行重新定向。实际上这并不会清除浏览器认证缓存但是会将其替换为某个无效的用户名和密码。因为Gallery会忽略无效的HTTP认证凭证,这样一来就能有效地使用户登出了。
- 使用Javascripy清楚IE认证缓存:
try {ldelim} {* http://msdn.microsoft.com/workshop/author/dhtml/reference/constants/clearauthenticationcache.asp *} document.execCommand("ClearAuthenticationCache"); {rdelim} catch (exception) {ldelim} {rdelim}
TryLogout页面重定向至FinishLogout页面的原因有二:
- 将浏览器认证缓存替换为某个无效用户名和密码。
- 检查用户确实登出了。如果登出了,FinishLogout页面会重定向会Gallery应用程序。不然的话吗就会显示一条警告,建议用户手动清除认证缓存(火狐浏览器中是清除私人数据(Private Data))。
TryLogout页面数据偶Javascript重定向至FinishLogout页面,并由某手动链接返回。无法使用302 Found状态,因为页面需要读取Internet Explorer JavaScript进行执行而我们无法在Location:header中置入无效的用户名和密码。
认证头(Authorization Header)[ ]
鉴于安全性考虑,Apache不传送认证:HTTP头至CGI,除非使用SECURITY_HOLE_PASS_AUTHORIZATION构建
server/util_script.c:
#ifndef SECURITY_HOLE_PASS_AUTHORIZATION else if (!strcasecmp(hdrs[i].key, "Authorization") || !strcasecmp(hdrs[i].key, "Proxy-Authorization")) { continue; } #endif
显然HTTP认证模块与mod_php兼容而不是PHP CGI。要解决此问题的话, HTTP认证模块定义一个URL重写规则来将Authorization: HTTP头的内容置入一个请求变量中:
/** * @see GalleryModule::getRewriteRules */ function getRewriteRules() { $rules = array(); /* * Only define the rule to pass the Authorization header to Gallery in a request variable if * it is already active, or if Gallery can't access HTTP usernames and passwords */ list ($ret, $rewriteApi) = GalleryCoreApi::newFactoryInstance('RewriteApi'); if ($ret) { $gallery->debug('Error in HttpAuthModule::getRewriteRules: ' . $ret->getAsText()); return $rules; } if (!isset($rewriteApi)) { return $rules; } list ($ret, $isCompatible) = $rewriteApi->isCompatibleWithApi(array(1, 1)); if ($ret) { $gallery->debug('Error in HttpAuthModule::getRewriteRules: ' . $ret->getAsText()); return $rules; } if (!$isCompatible) { return $rules; } list ($ret, $activeRules) = $rewriteApi->fetchActiveRulesForModule($this->getId()); if ($ret) { $gallery->debug('Error in HttpAuthModule::getRewriteRules: ' . $ret->getAsText()); return $rules; } if (!in_array('authorization', $activeRules)) { /* Check that Gallery can access HTTP usernames and passwords */ GalleryCoreApi::requireOnce('modules/httpauth/classes/HttpAuthHelper.class'); list ($ret, $success) = HttpAuthHelper::checkHttpAuth(); if ($ret) { $gallery->debug('Error in HttpAuthModule::getRewriteRules: ' . $ret->getAsText()); return $rules; } if ($success) { return $rules; } } /* Pass the Authorization header to Gallery in a request variable */ $rules['authorization'] = array( 'comment' => $this->translate('Authorization Header'), 'help' => $this->translate( 'Pass the Authorization header to Gallery in a request variable.'), 'keywords' => array( 'authorization' => array( 'pattern' => '(.+)', 'help' => $this->translate('Authorization header.'))), 'conditions' => array( array('test' => 'HTTP:Authorization', 'pattern' => '%authorization%'), array('test' => 'QUERY_STRING', 'pattern' => '!' . GalleryUtilities::prefixFormVariable('authorization') . '=')), 'options' => array('baseUrl' => '%{REQUEST_URI}'), 'flags' => array('QSA')); return $rules; }
如果Authorization: HTTP头没有被定义,HTTP认证模块就会尝试从该请求变量获取用户名和密码:
/** * Get the HTTP authtype, username, and password using either the PHP server variables or the * authorization request variable. * @return array string HTTP authtype * string HTTP username * string HTTP password */ function getHttpAuth() { $authtype = GalleryUtilities::getServerVar('AUTH_TYPE'); $username = GalleryUtilities::getServerVar('PHP_AUTH_USER'); $password = GalleryUtilities::getServerVar('PHP_AUTH_PW'); if (empty($username)) { $authorization = GalleryUtilities::getServerVar('HTTP_AUTHORIZATION'); if (empty($authorization)) { $authorization = GalleryUtilities::getRequestVariables('authorization'); if (empty($authorization)) { return array($authtype, $username, $password); } } list ($authtype, $authdata) = explode(' ', $authorization); list ($username, $password) = explode(':', base64_decode($authdata)); if (empty($username)) { return array($authtype, $username, $password); } } /* AUTH_TYPE is often not defined, assume a default */ if (empty($authtype)) { $authtype = 'Basic'; } return array($authtype, $username, $password); }
疑难解答[ ]
HTTP认证缺失[ ]
HTTP用户名和密码被发送到认证请求头中,但某些配置不会将认证头传送到脚本,例如Apache不会将认证头传送到CGI脚本,除非由'-D SECURITY_HOLE_PASS_AUTHORIZATION'构建。
我们可以使用Apache mod_rewrite将认证头通过请求变量传送到Gallery。http://httpd.apache.org/docs/2.2/rewrite/
URL重写模块被禁用[ ]
需要URL重写模块来自动将认证头通过请求变量传送到Gallery。
较差URL重写的配置[ ]
需要preGallery URL重写解析器来自动将认证头通过请求变量传送到Gallery。
'认证头'规则被禁用[ ]
自动将认证头通过请求变量传送到Gallery的URL重写规则被禁用。
如果你使用Apache mod_rewrite的话,可以手动添加以下内容到你的Gallery .htaccess文件:
RewriteCond %{HTTP:Authorization} (.+) RewriteCond %{QUERY_STRING} !g2_authorization= RewriteRule . %{REQUEST_URI}?g2_authorization=%1 [QSA]
TODO[ ]
- 添加某个请求变量或短URL,这样站点就能为某些而非其他的请求定义认证了
- 为忽略用户名和密码的服务器认证插件添加自助注册
- 添加HTTP认证登入页面
- 支持digest认证(PHP 5.1的特色,在goPHP5 deadline之后Gallery会对此作要求)