1

我是 Yii2 的新手,我需要使用 ldap 创建一个登录系统。关于它的信息不多,所以我希望有人能帮助我。

我安装了 edvlerblog/yii2-adldap-module 并且我已经成功实现了身份验证。

我的问题是,我希望在登录后拥有与使用高级模板相同的用户身份,并且能够使用 Yii::$app->user 功能。

官方示例通过 ActiveRecord 创建了实现 IdentityInterface 的 User:

http://www.yiiframework.com/doc-2.0/yii-web-identityinterface.html

我还发现了很多关于 Yii 版本 1 的示例。这是一个很好的示例:

https://www.exchangecore.com/blog/yii-active-directory-useridentity-login-authentication/

但仍然无法使其工作......可能是概念问题或语法问题,但无论如何我真的很感谢这里的一些帮助。

models/LoginForm.php 认证方式:

public function validatePasswordLdap($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUserLdap();
        if (!$user || !Yii::$app->ldap->authenticate($this->username,$this->password)) {
            $this->addError($attribute, 'Incorrect username or passwords.');
        }
    }
}

models/LoginForm.php 登录方法:

public function loginLdap()
{
    if ($this->validate()) {
        return Yii::$app->user->login($this->getUserLdap(), $this->rememberMe ? 3600 * 24 * 30 : 0);
    } else {
        return false;
    }
}

最后一个,getUser 方法。UserLdap 正在实施 IdentityInterface 但我不知道如何正确执行:

public function getUserLdap()
{
    if ($this->_user === false) {           
        $this->_user = UserLdap::findIdentity($this->username);
    }

    return $this->_user;
}
4

3 回答 3

2

我终于明白了其中的逻辑:

  • 当您登录到 LoginForm.php 视图时,获取用户名和密码并使用 validatePasswordLdap 进行验证。您必须在规则中指定验证密码的函数。

  • 然后如果 validate() 正常,它会使用登录中引入的用户名调用 FindIdentity。此函数必须返回一个 IdentityInterface 对象,因此首先您需要创建 User 对象,设置参数(电子邮件、电话、姓名等)并返回它。

  • 要在整个站点中使用登录/注销功能和 isGuest,您只需执行下面的 loginLdap 函数并将此用户对象传递给 Yii::$app->user->login 方法。

代码如下所示:

登录表单.php

public function rules()
{
    return [
        // username and password are both required
        [['username', 'password'], 'required'],
        // rememberMe must be a boolean value
        ['rememberMe', 'boolean'],
       // password is validated by validatePassword()
        ['password', 'validatePasswordLdap'],
    ];
}


public function validatePasswordLdap($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUserLdap();
        if (!$user || !Yii::$app->ldap->authenticate($this->username,$this->password)) {
            $this->addError($attribute, 'Incorrect username or passwords.');
        }
    }
}

public function loginLdap()
{
    if ($this->validate()) {
        return Yii::$app->user->login($this->getUserLdap(), $this->rememberMe ? 3600 * 24 * 30 : 0);
    } else {
        return false;
    }
}

用户.php

public static function findIdentity($id)
{

    $new_identity = new User();

    if ($user_ldap_info = Yii::$app->ldap->user()->infoCollection($id, array("*"))){
        $new_identity->setId($user_ldap_info->samaccountname);
        $new_identity->setEmail($user_ldap_info->mail);
        $new_identity->setUsername($user_ldap_info->displayName);   
    }

    return $new_identity;
}

public function setEmail($email)
{
    $this->email = $email;
}

public function setUsername($username)
{
    $this->username = $username;
}

public function setId($id)
{
    $this->id = $id;
}

LoginForm.php 内部

public function getUserLdap()
{
    if ($this->_user === false) {           
        $this->_user = User::findIdentity($this->username);
    }

    return $this->_user;
}

编辑:由于供应商 ADLDAP 更新,我不得不将 findIdentity 更改为:

public static function findIdentity($id)
{
    $new_identity = new User ();

    if ( $user_ldap_info = Yii::$app->ldap->users()->find($id) ) {
        $new_identity->setId ( $user_ldap_info->samaccountname [0] );
        $new_identity->setEmail ( $user_ldap_info->mail[0] );
        $new_identity->setUsername ( $user_ldap_info->givenname [0] );
    }

    return $new_identity;
}
于 2015-05-06T07:22:06.777 回答
0

我希望找到 Daniel Stolf 发表了他所描述的工作示例。

在搜索时,我想知道这是否已通过最新的 Larvel 5.1 完成并发现:

https://libraries.io/github/sroutier/laravel-5.1-enterprise-starter-kit

使用 sroutier/eloquent-ldap 的可选 LDAP/AD 身份验证,具有以下选项:

Automatically creates local account for LDAP/AD users on first login.
Automatically assign to matching local roles based on LDAP/AD group membership.
Refresh role assignment on login.

这正是我一直在寻找的。我更喜欢使用 Yii2 框架,但由于 Yii2 缺乏这样的功能集成扩展,我想我会转向 Laravel。

除非 Konrad 为 Yii2 重写本指南:http: //blog.realhe.ro/windows/yii-role-mapping-based-on-active-directory

于 2015-10-09T12:54:21.307 回答
0

首先事先声明:发布的代码片段都是基本示例。您需要自己处理琐碎的异常和进一步的逻辑。


我将发布一个快速 hack,以使用 Yii2 高级模板实现简单的 AD 身份验证,该模板将采用用户名/密码并针对 MS Active Directory 域控制器验证此组合。此外,它还会检查用户给定的组成员身份,因此只有具有该组的用户才能登录。

我们假设:

  • 用户(特别是用户名)必须存在于当前用户表中(查看授权指南以构建 rbac结构)。我们进一步假设我们数据库中的用户名与您要针对 AD 进行身份验证的用户名相同。
  • 您已经为 Yii2 正确设置了Adldap2包装器(如alexevdv/yii2-adldap)或将 Adladp2 作为供应商模块加载。从包装器中受益: 您可以在应用程序配置的组件部分中配置 adldap2 类,然后您可以将包装器用作 Yii2 组件。
  • 您的 PHP 环境使用 LDAP 扩展(例如在 debian 发行版上运行类似apt-get install php5-ldap的东西)。
  • 您有一些管理员凭据可以连接到具有以您想要的方式查询 AD 的权限的域控制器。

因此,让我们从基本设置开始。

设置包装器配置(例如 config/main-local.php)。

'components' => [
    'ldap' => [
        'class' => 'alexeevdv\adldap\Adldap',
        'options' => [
            'account_suffix' => '@stackoverflow.com',
            'domain_controllers' => ['dc1.stackoverflow.com', 'dc2.stackoverflow.com'],
            'base_dn' => 'dc=stackoverflow,dc=com',
            'admin_username' => 'someusername',
            'admin_password' => 'somepassword',
            'use_ssl' => true,
            'port' => '636'
        ],
    ],
],

我想在 ldap 和本地身份验证之间轻松切换。配置一些本地参数以具有全局可访问的应用程序参数(例如 config/params-local.php)。

return [
    'adminEmail' => 'admin@example.com',
    'authOverLdap' => true,
    'ldapGroup' => 'someldapgroup',
];

编辑您的 LoginForm.php,尤其是validatePassword函数(例如 common/models/LoginForm.php)。

/**
 * Validates the password.
 * This method serves as the inline validation for password.
 * If the authOverLdap attribute is set in the params config,
 * user and password will be authenticated over ldap
 *
 * @param string $attribute the attribute currently being validated
 * @param array $params the additional name-value pairs given in the rule
 */
public function validatePassword($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUser();
        // to switch between the auth-methods
        $authOverLdap = \Yii::$app->params['authOverLdap'];
        if ($authOverLdap) {
            if (!$user || !$user->validateCredentialsOverLdap($user->username, $this->password)) {
                $this->addError($attribute, 'Some error text.');
            }
        } else {
            if (!$user || !$user->validatePassword($this->password)) {
                $this->addError($attribute, 'Some error text.');
            }
        }
    }
}

在处理 LDAP 身份验证的用户模型中添加validateCredentialsOverLdap函数(例如 /common/models/User.php)。

/**
 * Validates a user/password combination over ldap
 *
 * @param string $username username to validate over ldap
 * @param string $password password to validate over ldap
 * @return boolean if the provided credentials are correct and the user is a member of **ldapGroup**
 */
public function validateCredentialsOverLdap($username, $password)
{
    $authSuccess = false;
    // checking the supplied credentials against the ldap (e.g. Active Directory)
    // first step: the user must have a valid account
    // second step: the user must be in a special group
    $authOk = \Yii::$app->ldap->authenticate($username, $password);
    if ($authOk) {
        $adUser = \Yii::$app->ldap->users()->find($username);
        // the user must be in special group (set in Yii params)
        if($adUser->inGroup(\Yii::$app->params['ldapGroup'])) {
            $authSuccess = true;
        }
    }

    return $authSuccess;
}

免责声明:

  • 不要复制和粘贴这些片段!你必须知道你在做什么!
  • 这将向您展示一个示例,并为您提供使用包装器和 Yii2 框架实现 AD 身份验证的提示。
  • 我在围墙花园内联网中运行此代码!
  • 永远使用SSL等安全层通过 LDAP 进行通信!您不知道谁在嗅探您可能安全的网络中的流量。您处理用户凭据。这可能是个大问题,尤其是在单点登录环境中!别傻了。
于 2016-03-18T07:51:58.963 回答