Files
人事系统开发 1ba6efd8ed MRBS 1.12.2 等保2.0二级整改完整提交
包含:登录失败锁定、90天密码有效期、30分钟会话超时、
强制改密、登录审计日志、屏幕水印、企业背景图、
备案信息固定底部、favicon、JS空集合保护、
会话过期体验优化(403 JSON)、display_errors 关闭、
固定 key 根治 Integrity check failed 等全部改动

注意:config.inc.php/.htaccess/.user.ini 含敏感信息,
通过 .gitignore 排除,勿推送到公开仓库。
2026-09-09 16:55:02 +08:00

191 lines
4.5 KiB
PHP

<?php
namespace MRBS\Auth;
use MRBS\Exception;
use Webklex\PHPIMAP\ClientManager;
use Webklex\PHPIMAP\Exceptions\AuthFailedException;
use Webklex\PHPIMAP\Exceptions\ImapServerErrorException;
/**
* Authentication scheme that uses IMAP as the source for user authentication. If the PHP version is
* less than 8.0, it requires you to have the PHP 'imap' extension installed and enabled.
*
* To use this authentication scheme, set the following things in config.inc.php:
*
* $auth["realm"] = "MRBS"; // Or any other string
* $auth["type"] = "imap_php";
*
* You must also configure at least:
*
* $auth["imap_php"]["hostname"] = "mailserver.hostname";
*
* You can also specify any of the following options:
*
* $auth["imap_php"]["port"] = 993; // Specifies the port number to connect to
* $auth["imap_php"]["ssl"] = true; // Use SSL
* $auth["imap_php"]["tls"] = true; // Use TLS
* $auth["imap_php"]["novalidate-cert"] = true; // Turn off SSL/TLS certificate validation
*
* Then, you may configure admin users:
*
* $auth["admin"][] = "imapuser1";
* $auth["admin"][] = "imapuser2";
*/
class AuthImapPhp extends Auth
{
private $canUseWebklex;
public function __construct()
{
assert(
version_compare(MRBS_MIN_PHP_VERSION, '8.0') < 0,
'The code below is no longer required.'
);
// The imap extension was removed in PHP 8.4 and so we use the Webklex/PHPIMAP library
// instead. However this requires PHP 8.0 or greater.
$this->canUseWebklex = (version_compare(PHP_VERSION, '8.0') >= 0);
if (!$this->canUseWebklex && !function_exists('imap_open'))
{
throw new Exception("The imap extension is not installed on this server.");
}
}
public function validateUser(
#[\SensitiveParameter]
?string $user,
#[\SensitiveParameter]
?string $pass)
{
global $auth;
// If required, check that the username is from the permitted domain
if (isset($auth['imap_php']['user_domain']))
{
if (!filter_var($user, FILTER_VALIDATE_EMAIL))
{
return false;
}
list(, $domain) = explode('@', $user);
if ($domain != $auth['imap_php']['user_domain'])
{
return false;
}
}
if (!$this->canUseWebklex)
{
return $this->validateUserLegacy($user, $pass);
}
$cm = new ClientManager();
$config = [
'host' => $auth['imap_php']['hostname'],
'username' => $user,
'password' => $pass,
'protocol' => 'imap'
];
// The defaults are chosen to be compatible with the legacy behaviour.
$config['port'] = $auth['imap_php']['port'] ?? 143;
$config['validate_cert'] = empty($auth['imap_php']['novalidate-cert']);
if (!empty($auth['imap_php']['ssl']))
{
$config['encryption'] = 'ssl';
}
elseif (!empty($auth['imap_php']['tls']))
{
$config['encryption'] = 'tls';
}
else
{
$config['encryption'] = '';
}
try {
$client = $cm->make($config);
$client->connect(); //Connect to the IMAP Server
return $user;
}
catch (ImapServerErrorException | AuthFailedException $e) {
// Don't do anything with these exceptions: they are normal when
// authentication fails.
}
catch (\Exception $e) {
// We weren't expecting any other exceptions so trigger an error.
$message = "Caught exception '" . get_class($e) . "'\n";
$message .= $e->getMessage() . "\n" . $e->getTraceAsString();
trigger_error($message, E_USER_WARNING);
}
return false;
}
private function validateUserLegacy(
#[\SensitiveParameter]
?string $user,
#[\SensitiveParameter]
?string $pass)
{
global $auth;
$location = '{' . $auth['imap_php']['hostname'];
if (isset($auth['imap_php']['port']))
{
$location .= ':' . $auth['imap_php']['port'];
}
$location .= '/imap';
if (!empty($auth['imap_php']['ssl']))
{
$location .= '/ssl';
}
if (!empty($auth['imap_php']['tls']))
{
$location .= '/tls';
}
if (!empty($auth['imap_php']['novalidate-cert']))
{
$location .= '/novalidate-cert';
}
$location .= '}INBOX';
$mbox = imap_open($location, $user, $pass);
if ($mbox !== false)
{
imap_close($mbox);
return $user;
}
return false;
}
/**
*/
public function canValidateByEmail() : bool
{
return true;
}
/**
*/
public function canValidateByUsername() : bool
{
return false;
}
}