読者です 読者をやめる 読者になる 読者になる

orz.conf

技術メモ✍

PHPでActiveDirectory接続クラス

php

phpでActiveDirectoryに接続するクラスを書いてみます。

機能としては、認証処理とパスワード変更処理が出来るもの
とします。

プロパティ
・ActiveDirectoryのホスト(IPアドレス)
・ActiveDirectoryのAdministrator権限を持ったユーザ★
・ActiveDirectoryのAdministrator権限を持ったユーザのパスワード★
ドメイン
・ベースDistinguishName★

★つきのプロパティはパスワード変更をする際に必要となります。

色々と説明を省くために、クラス内で直接必要な変数の情報を記載しました。
コンフィグとして別ファイルから読み込むほうが一般的かと思います。適宜修正してください。

まずはコンストラクタ

function __construct(){
	$connInfo = array(
		'host'		  => 'ldaps://192.168.1.10',
		'admin_user'	=> 'admin',
		'admin_pass'	=> 'password',
		'domain_name'   => 'example.co.jp',
		'base_dn'	   => 'DC=example,DC=co,DC=jp'
	);

	$this->host = $connInfo['host'];
	$this->admin_user = $connInfo['admin_user'];
	$this->admin_pass = $connInfo['admin_pass'];
	$this->domain_name = $connInfo['domain_name'];
	$this->base_dn = $connInfo['base_dn'];

	if(!$this->ldapconn = ldap_connect($this->host)){
		file_put_contents( "/var/log/ldap_log.log", "ldap_connect failed" );
	}
}

必要なプロパティに値を入れます。
今回はhostにldapsを指定しています。
もし、bind認証しかしないのであればldapでも良いと思います。
ldapsを使うということはssl通信をするというわけで、証明書を入れる
必要があります。これについてはまた別の記事に記載します。

ldap_connectしActiveDirectoryサーバと接続します。

失敗するとFALSEが返ってきます。
もし失敗するようであれば、ActiveDirectoryのサーバと
通信できるか、サービスが起動しているか
このphpを動かしているサーバのネットワークに問題は
ないか等単純なところを疑いましょう。

file_put_contentsの行は適宜ログ出力クラス等に修正してください。

次にbind認証メソッドです。

function ad_bind($userName, $userPass){
	if($userPass === ""){
		return false;
	}

	$userId = $userName."@".$this->domain_name;

	ldap_set_option($this->ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
	if(ldap_bind($this->ldapconn, $userId, $userPass)){
		return true;
	}else{
		return false;
	}
}

パスワードを空としてbind認証を行うと、なぜかtrueが返ってくるので
コーディングで空かどうか判定しましょう。

ldap_set_optionでプロトコルバージョンを3とします。

ldap_bindでbind認証を行います。
認証出来ればtrue、そうでなければfalseととてもシンプルな戻り値です。


続いてパスワード変更メソッドです。

function ad_modify($userName, $userPass){
	$adminId = $this->admin_user."@".$this->domain_name;
	$userId = $userName."@".$this->domain_name;

	//DNを取得
	$filter = array("dn");
	$ls = ldap_search($this->ldapconn, $this->base_dn, "sAMAccountName=$userName", $filter);
	$userInfo = ldap_get_entries($this->ldapconn, $ls);

	$entry["unicodePwd"] = mb_convert_encoding("\"" . $userPass . "\"", "UTF-16LE");

	$rtn = ldap_mod_replace($this->ldapconn, $userInfo[0]['dn'], $entry);
	return $rtn;
}

以下が完成系です。

<?php
class Ad_Conn
{
	function __construct(){
		$connInfo = array(
			'host'		  => 'ldaps://192.168.1.10',
			'admin_user'	=> 'admin',
			'admin_pass'	=> 'password',
			'domain_name'   => 'example.co.jp',
			'base_dn'	   => 'DC=example,DC=co,DC=jp'
		);

		$this->host = $connInfo['host'];
		$this->admin_user = $connInfo['admin_user'];
		$this->admin_pass = $connInfo['admin_pass'];
		$this->domain_name = $connInfo['domain_name'];
		$this->base_dn = $connInfo['base_dn'];

		if(!$this->ldapconn = ldap_connect($this->host)){
			file_put_contents( "/var/log/ldap_log.log", "ldap_connect failed" );
		}
	}

	function __destruct() {
		ldap_close($this->ldapconn);
	}

	function ad_bind($userName, $userPass){
		if($userPass === ""){
			return false;
		}

		$userId = $userName."@".$this->domain_name;

		ldap_set_option($this->ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
		if(ldap_bind($this->ldapconn, $userId, $userPass)){
			return true;
		}else{
			return false;
		}
	}

	function ad_modify($userName, $userPass){
		$adminId = $this->admin_user."@".$this->domain_name;
		$userId = $userName."@".$this->domain_name;

		//DNを取得
		$filter = array("dn");
		$ls = ldap_search($this->ldapconn, $this->base_dn, "sAMAccountName=$userName", $filter);
		$userInfo = ldap_get_entries($this->ldapconn, $ls);

		$entry["unicodePwd"] = mb_convert_encoding("\"" . $userPass . "\"", "UTF-16LE");

		$rtn = ldap_mod_replace($this->ldapconn, $userInfo[0]['dn'], $entry);
		return $rtn;
	}
}
?>