Criando um diretório de endereços WEB PHP + LDAP

Acontece que uma campanha (relativamente) grande teve muitos escritórios remotos com um número razoável de usuários. Todos os escritórios estão conectados em uma rede com um domínio comum, cada escritório foi definido no Active Directory (doravante denominado AD) como uma Unidade Organizacional (OU), na qual os usuários já foram criados.

Era necessário dar aos usuários a oportunidade de obter de forma rápida e fácil os dados de contato do funcionário desejado no AD e libertar os administradores do sistema da rotina de edição de um arquivo de texto que desempenhava o papel de um catálogo de endereços.

Não havia opções adequadas e prontas para resolver o problema, então tive que fazer tudo com minhas próprias mãos e cabeça.

Vamos começar com o fato de que primeiro você precisa decidir o que usar, é simples - o diretório final deve estar disponível para todos os usuários do domínio por meio de um navegador. A primeira coisa que vem à mente é PHP em conjunto com ldap, e nós os usaremos. Considero a grande vantagem de usar PHP sua relativa simplicidade - qualquer administrador de sistema com um pouco de conhecimento será capaz de fazer as alterações necessárias no código, se necessário, sem muito esforço.

Então, vamos começar. Primeiro, vamos definir os parâmetros para conexão ao domínio:

$srv ="SERVER";
$srv_domain ="DOMAIN.COM";
$srv_login ="USERNAME@".$srv_domain; 
$srv_password ="PASSWORD";

O próximo ponto é determinar em qual UO procuraremos os usuários. Faremos isso interceptando valores de $_GET['place']. Por exemplo, se o usuário for para o endereço servidor/index.php?place=primeiro, então a variável $lugar será atribuído o valor primeiro.

$place = (@$_GET['place']);
$doscript=true;
switch($place){ 
case "first" :
	$dn ="OU=ou1,OU=DOMAIN,dc=DOMAIN,dc=COM";			
	break;
case "second":
	$dn ="OU=ou2,OU=DOMAIN,dc=DOMAIN,dc=COM";			
	break;
	//здесь можно добавить ещё условий.
default:
	$doscript=false; 
	break;
}
if (!$doscript) include "main_table.html";

Variável $doscript é necessário para armazenar o valor - quer tenhamos definido a UO na qual procuraremos os usuários ou não. Se não houver correspondências listadas no “switch-case”, então $doscript=false, a parte principal do script não será executada e a página inicial “main_table.html” será exibida (vou falar sobre isso no final).

Se definimos uma UO, prosseguimos para outras ações: começamos a desenhar uma página de diretório para o usuário:

else if ($doscript) {
{echo "
<!DOCTYPE html> 
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<link rel='shortcut icon' href='ico.png'>
<meta charset='windows-1251/ '>

Incluímos estilos para uma aparência mais agradável (sim, eles poderiam ser incluídos como um arquivo css, mas algumas versões do IE não aceitam estilos definidos desta forma, então você deve escrevê-los diretamente no script):

<style>
	*{text-align: center; font-family:tahoma; font-size:14px;}
	a{text-decoration: none; color: #000;}
	a:hover{text-decoration: underline; color: #0059FF;}
	#bold{text-decoration: none; font-weight: 600;font-size:20px;}
	#table,tr,td{border-style:solid;border-width:1px;	border-collapse:collapse;padding:5px; height:22px;border-color:#7d7d7d;}
	/* Нечетные строки */#table tbody tr:nth-child(odd){background: #fff;}
	/* Четные строки */   #table tbody tr:nth-child(even){background: #F7F7F7;}	
	#noborder{border-width: 0 px; border-style: none;}	
	#sp30px{text-indent: 30px;text-align: justify;}
	#smallsize{font-family:tahoma; text-indent: 5px; text-align:left; font-size:12px;}
	#top {background: #ffffff;
		text-align: center;
		left:0;
		top:0px;
		table-layout: fixed;
		border-style:solid;
		border-width:0px;
		border-collapse:collapse;
		padding:0px;
		height:22px;
		border: 0px;
		z-index: 99999;
		display:block;
		width:80px;
		opacity: 0.6;
		filter: alpha(Opacity=60);
		height:100%;
		position:fixed;}
	#top:hover{background: #afafaf;opacity: 100;filter: alpha(Opacity=100);text-decoration: none;color: #000000;}
	.smalltext{padding-top: 1px;
		padding-bottom: 1px;
		text-align: bottom;
		font-family:tahoma;
		color: #a0a0a0;
		line-height: 7px;
		font-size: 10px;}
	.smalltext:hover{color: #0000ff;}		
	.transition-rotate {position: relative;
		z-index: 2;
		margin: 0 auto;
		padding: 5px;
		text-align: center;
		max-width: 500px;
		cursor: pointer;
		transition: 0.1s linear;}
	.transition-rotate:hover {-webkit-transform: rotate(-2deg);	transform: rotate(-2deg);}
	#lineheight{
		text-align: left;
		line-height: 1px;
		text-decoration: none;
		font-weight: 600;
		font-size:20px;}
</style>

Terminamos os estilos, agora escrevemos o título da aba e desenhamos um link conveniente para retornar à página principal:

<title>Adressbook of «YourMegaCompanyName»</title>	
</head>
<body style='background-color:#ffffff;'>";
}
echo "
<table id='top'><tr><td id='top'>
<a href='index.php?place=main' id='top' >
<br><br><br>
<img src='back_to_main.png' alt='' border='0' width='75' height='60'/>
<p>На главную</p></a>
</td></tr></table>
";

Definimos filtros de pesquisa por AD e obtemos dados sobre a UO:

$filter ="(&(objectcategory=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"; //все пользователи, кроме отключенных.
$filter2 ="(objectCategory=OrganizationalUnit)"; // для получения информации о OU
$ds=ldap_connect($srv);   
if ($ds) { 
    $r=ldap_bind($ds,$srv_login,$srv_password);;     
	ldap_set_option($ds,LDAP_OPT_REFERRALS, 0);
	ldap_set_option($ds,LDAP_OPT_PROTOCOL_VERSION,3);
	$sr=ldap_search($ds,$dn ,$filter );   
    ldap_sort($ds,$sr, "givenname");
    $info = ldap_get_entries($ds, $sr); 
    $sr2=ldap_search($ds,$dn ,$filter2 );   
    $placeinfo = ldap_get_entries($ds, $sr2); 
$PlaceName = $placeinfo[0]["l"][0];  			// name of place
$PlaceAddres = $placeinfo[0]["street"][0];		// address of place
$PlaceMail = $placeinfo[0]["description"][0]; 	// mail of place
$PlacePhone = $placeinfo[0]["st"][0]; 		// phone of plase

A seguir, projetamos o topo da página:

echo"<table align='center' height = '80'>
	<td id='noborder' ><div id='lineheight'>". $PlaceName ."</div></td></tr>
	<tr><td id='noborder' >". $PlaceAddres ."</td></tr>
    </table>
<table align='center' id='table'>
	<tr><td width='35' bgcolor = #f0f0e4>  № </td>
	<td width='300' bgcolor = #f0f0e4> Name </td>
	<td width='250' bgcolor = #f0f0e4> E-mail </td>
	<td width='60' bgcolor = #f0f0e4> Phone </td>
	<td width='150' bgcolor = #f0f0e4> Mobile </td></tr>
	<tr><td></td><td> Данные OU </td><td>";
echo "<div class='transition-rotate'><a href=mailto:" . $PlaceMail .">" . $PlaceMail ." </a></div>";
echo "</td><td width='150'> " . $PlacePhone ." </td><td> - </td></tr>";

Em seguida, recebemos e processamos os dados do usuário em um loop, enquanto para ocultar algumas contas (por exemplo, de serviço), simplesmente inserimos “ocultar” no campo “sala” nos detalhes do usuário no AD, tais usuários não serão exibido no diretório:

for ($i=0; $i<$info["count"];$i++) { 
$UserHide = $info[$i]["physicaldeliveryofficename"][0];
if ($UserHide != 'hide') {
$UserName = $info[$i]["cn"][0];                //Имя пользователя
$UserPosition = $info[$i]["title"][0]; 		// Должность
$UserMail = $info[$i]["mail"][0];			//mail
if (!$UserMail)) $UserMail = "-";                  //если нет данных о ящике в AD, то отображаем прочерк
$UserIpPhone = $info[$i]["ipphone"][0];		//ip phone
	if (!$UserIpPhone) $UserIpPhone = "-";    //если нет данных о ящике в AD, то отображаем прочерк
$UserMobile = $info[$i]["mobile"][0];		//mobile
	if (!$UserMobile) $UserMobile = "-";     //если нет данных о ящике в AD, то отображаем прочерк

A propósito, se você precisar obter o valor de outro atributo, lembre-se (isso é importante):
na solicitação passamos o nome do atributo minúscula em letras, caso contrário não funcionará.

E insira os dados recebidos na tabela:

    echo "<tr>
	<td>". $n+=1 ."</td>
	<td> ". $UserName ."<br> <div class='smalltext'>". $UserPosition ."</div></td><td>"; //	Имя пользователя и должность 
	if ($UserMail !='-') echo "<div class='transition-rotate'><a href=mailto:'$UserMail'>$UserMail  </a></div>";    // если у пользователя есть e-mail создаём ссылку на отправку письма
	else echo "-"; //если нет e-mail - ставим прочерк.
 	echo "<td> ". $UserIpPhone ." </td>
 	<td> ". $UserMobile ." </td></tr>";
	}
}
echo "</table>";

A seguir, fechamos a conexão ldap, ou exibimos uma mensagem sobre a impossibilidade de conexão ao servidor:

ldap_close($ds); 
} 
else echo "<h4>Unable to connect to LDAP server</h4>"; 
echo '<br><br><br></body></html>';}

O arquivo “main_table.html” visto de dentro é uma página HTML simples com links e se parece com isto:

<head>
<link rel="shortcut icon" href="ico.png"/>
<meta charset="windows-1251"/>
<title>Adressbook of «YourMegaCompanyName»</title>
</head>
<body style='background-color:#ffffff;'>
<center><a href=index.php><IMG border="none" src="logo.png"/></a></center>
<center><b>Places and offices</b></center>
<br>
<table border="0" width="450" bgcolor="#dddddd" align="center" valign="middle" CELLSPACING="0">

<tr id="space"><td></td></tr>
<tr><td align="left" id="abz"><a href="index.php?place=ou1">OU1</a></td></tr>
<tr id="space"><td></td></tr>
<tr><td align="left" id="abz"><a href="index.php?place=ou2">OU2</a></td></tr>

</table></body></html>

Se meu código ajudar alguém, ficarei feliz, use-o!

Você também pode editá-lo livremente como desejar (melhorar/piorar) e distribuí-lo por qualquer meio.

Obrigado!

Fonte: habr.com

Adicionar um comentário