commifreak/yii2-ldap-auth

另一个Yii2 LDAP认证扩展

安装数: 2,051

依赖: 0

建议者: 0

安全: 0

星星: 1

关注者: 2

分支: 0

开放问题: 0

类型:yii2-extension

v1.4.1 2024-01-26 06:50 UTC

README

此扩展为您的yii2应用程序添加了一个简单的LDAP认证机制

功能

  • 尝试绑定到在LoginForm中输入的用户名/凭证所选的域
  • 成功绑定后读取用户数据属性,以获取sid和其他值

特性

  • 通过LDAP进行用户登录
  • 读取自定义LDAP属性
  • 基于IPFilter的域自动检测
  • 通过检查每个结果sidHistory来过滤结果
  • 可选的查询缓存

安装

安装的首选方式是通过composer

composer require commifreak/yii2-ldap-auth

设置

您可以使用它作为独立组件,也可以将其添加为组件

[
   'components' => [
      'ldap' => [
            'class' => 'commifreak\yii2\LdapAuth',
            'filterBySidhistory' => false, // Filter by checking sidHistory?
            'enableCache' => false,
            'forceApcuCache' => false,
            'apcuCacheTtl' => 3600,
            'domains' => [
                ['name' => 'Domain1', 'hostname' => 'domain1.tld', 'autodetectIps' => ['172.31.0.0/16', '192.168.178.0/24', '127.0.0.1'], 'baseDn' => 'DC=Domain1,DC=tld', 'publicSearchUser' => 'example@domain', 'publicSearchUserPassword' => 'secret'],
                ['name' => 'Domain2', 'hostname' => '192.168.178.14', 'autodetectIps' => ['192.168.178.55'], 'baseDn' => 'DC=Domain2,DC=tld', 'publicSearchUser' => 'example@domain', 'publicSearchUserPassword' => 'secret'],
                //...
            ],
        ],
     ]
]

如果您不希望特定域使用IP,则可以省略autodetectIps

如果您想使用加密,则可以设置useSSL

注意!您需要定义baseDn。这定义了函数将在其中搜索用户数据的baseDN!

使用方法

有5个基本函数

  • autoDetect($overrideIp)
    • 尝试检测用户的客户端IP(支持代理)并确定要使用的域
  • login($username, $password, $domainKey, $fetchUserDN)
    • 尝试连接到域并以$username$password的身份绑定
    • $domainKey定义要使用的域(由autoDetect检测或通过传递配置数组的键值传递)
      • 如果您将其设置为false或不传递任何内容,登录函数将遍历每个域并尝试登录(默认)。
    • $fetchUserDN确定用户DN,如果您想通过用户的DN而不是username@hostname进行绑定
  • fetchUserData($attributes)
    • 查询LDAP以获取登录用户并获取一些属性(可调整的属性列表)
  • searchUser($searchFor, $attributes, $searchFilter, $domainKey, $onlyActiveAccounts, $allDomainsHaveToBeReachable)
    • 在LDAP目录中搜索用户。这需要在组件选项中配置搜索用户。
    • 这些选项允许您定义您想要返回的属性以及在哪个属性中搜索(默认为lastname,firstname,username和class=person)。
    • $domainKey允许您设置一个固定的域(例如来自autoDetect)进行搜索。否则,将在每个域中进行搜索。
    • $onlyActiveAccounts允许您决定是否只返回活动账户或所有账户。默认为false!
    • $allDomainsHaveToBeReachable:如果所有配置的域都需要可访问才能获得结果,则为True。如果其中一个不可访问,则返回false。
  • updateAttributes允许您更新用户属性
    • $attributes 属性(数组键是属性名称,数组值是属性值)
    • $dn 应该更新的DN - 如果未提供,则使用之前检查的最终值。

示例

视图

我在LoginForm中添加了一个新的属性location,它包含域键。

<?= $form->field($model, 'location')->widget(\kartik\select2\Select2::className(), [
        'data' => \yii\helpers\ArrayHelper::getColumn(Yii::$app->ldap->domains, 'name'),
        'options' => ['placeholder' => 'Select a domain ...'],
        'pluginOptions' => [
            'allowClear' => true
        ],
    ]) ?>

要使用autoDetect功能,您现在不需要做任何事情!插件会自动处理!您只需将位置下拉菜单设置为0,方法是在您的LoginForm中设置以下内容

    public function init()
    {
        parent::init(); // TODO: Change the autogenerated stub
        $this->location = 0; // Set it to the first entry, which is now always autodetected
    }

登录

这是基于默认的LoginForm->login()函数

public function login()
    {
        if (!$this->validate()) {
            return false;
        }

        // At this point we filled the model - now we ask the LDAP if the entered data is correct
        
        /** @var LdapAuth $ldap */
        $ldap = Yii::$app->ldap;


        if ($ldap->login($this->username, $this->password, $this->location)) { // or if ($ldap->login($this->username, $this->password, $this->location, true)) if you want to use `$fetchUserDN`-feature!
            $userData = $ldap->fetchUserData();
            if ($userData) {
                $user = User::find()->where(['sid' => $userData['sid']])->one();

                if (!$user) {
                    $user = new User();
                    $user->sid = $userData['sid'];
                }

                $user->email = $userData['mail'];
                $user->firstname = $userData['givenname'];
                $user->lastname = $userData['sn'];
                $user->phone = $userData['telephonenumber'];

                $user->validate();
                $user->save();

                return Yii::$app->user->login($user, $this->rememberMe ? 3600 * 24 * 30 : 0);
            }
        } else {
            Yii::$app->session->setFlash('error', 'Login gescheitert!');
        }
    }

这也尝试将用户数据与LDAP同步。

用户属性更新

/** @var LdapAuth $ldap */
$ldap = \Yii::$app->ldap;

if (!$ldap->login(\Yii::$app->user->identity->sid, $this->userPassword, false, true)) {
    return false;
}

$updateAttrs = [];

if (!empty($this->phone)) {
    $updateAttrs['telephonenumber'] = $this->phone;
}

if (!empty($this->room)) {
    $updateAttrs['physicaldeliveryofficename'] = $this->room;
}

if (!$ldap->updateAttributes($updateAttrs)) {
    return false;
}

数据库

我已经按照以下方式添加/修改了用户表,添加了sid、firstname、lastname和phone列

CREATE TABLE `user`
(
  `id`             int(10) unsigned NOT NULL AUTO_INCREMENT,
  `sid`            varchar(255) DEFAULT NULL,
  `email`          varchar(256) NOT NULL,
  `firstname` varchar(255) DEFAULT NULL,
  `lastname` varchar(255) DEFAULT NULL,
  `phone` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `create_user` int(11) DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `update_user_id` int(11) DEFAULT NULL,
  `auth_key` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `auth_key_UNIQUE` (`auth_key`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;