2017-08-31 45 views
0

這些都是我的先決條件:LDAP - 尋找一種更好的方式在PHP來管理用戶/ MySQL的

  • 用戶是通過Active Directory
  • 管理在LDAP他們被分配到確定這些權利團體用戶
  • 安全登錄NTLM

現在我檢查,看看如果用戶是某組的成員顯示一些數據之前:

if(is_allowed(USER, '(memberof=CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local)')): 
    display some data 
endif; 

function is_allowed($check, $filter) { 
    // connect to ldap 
    $ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server."); 
    // binding to ldap server 
    ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn)); 

    // search for $filter 
    $result = ldap_search($ldapconn, LDAP_TREE, $filter) or die("Error in search query: " . ldap_error($ldapconn)); 
    $data = ldap_get_entries($ldapconn, $result); 

    // check if user is part of LDAP_TREE 
    if (!in_multiarray($check, $data)): 
     // all done? clean up! 
     ldap_close($ldapconn); 
     return false; 
    endif; 
    // all done? clean up! 
    ldap_close($ldapconn); 
    return true; 
} 

function in_multiarray($elem, $array) { 
    while (current($array) !== false): 
     if (current($array) == $elem): 
      return true; 
     elseif(is_array(current($array))): 
      if(in_multiarray($elem, current($array))): 
       return true; 
      endif; 
     endif; 
     next($array); 
    endwhile; 
    return false; 
} 

現在,如果我想將用戶分配到例如我運行下面的一票:

// connect to ldap 
$ldapconn = ldap_connect(LDAP_HOST); 
// binding to ldap server 
ldap_bind($ldapconn, LDAP_USER, LDAP_PASS); 

// search for $filter 
$result = ldap_search($ldapconn, LDAP_TREE, LABORATORY); 
$data = ldap_get_entries($ldapconn, $result); 
utf8_encoder($data); 
for ($i=0; $i<$data["count"]; $i++): 
    echo "<tr><td><label class=\"label\"><input type=\"checkbox\" name=\"user[]\" value=\"".$data[$i]["cn"][0]."\" />".$data[$i]["cn"][0]."</label></td></tr>"; 
endfor; 
ldap_close($ldapconn); 

和數據庫中我只是把名字。如果我賦予它更多的用戶我單獨他們「」這樣的:

$users = NULL; 
     foreach($c_post['user'] as $value): 
      $users = $users.$value.", "; 
     endforeach; 

結果會是這樣的,在我的數據庫:Alex Foo, Peter Bar

而且從數據庫讀取我只用一個簡單地爆炸來分離它們。

$iduser = explode(", ", $row->iduser);

也是爲了得到我使用此過濾器的當前用戶瀏覽:

// User based on Windows-Login (Look up user currently browsing) 
define('LDAP_SELF', '(sAMAccountName='.substr($c_server['REMOTE_USER'], 11).')'); 

現在有這個設置這樣說,這是很容易的添加用戶,管理自己的權利等上。一旦你掌握了那些過濾LDAP的用法,即使是部門主管等等之間的定位也是相當容易的。

但對我來說,在我的代碼中使用會變得很痛苦。現在我想發送消息並根據用戶獲取一些統計信息,每次都會綁定到LDAP並查找用戶。這是我第一次使用LDAP/Active Directory,在此之前,我剛剛在MySQL中擁有我的表格,該表格充滿了用戶和他們的ID。根據代碼中的ID存儲,管理和執行操作似乎更容易,然後就是現在。

  • 有什麼我可以在我的代碼或使用LDAP的方式提高?
  • 我是否正確地使用LDAP? (我知道答案將基於意見,但只要我不濫用LDAP與我的代碼我很好,我猜)
  • 如何保存每次綁定到LDAP相比,只是有我的數據庫中的用戶?
  • 如果不安全使用LDAP,我應該每天運行一次某些腳本向用戶填充表格?
  • 更簡單的方式來執行下面的東西?

作爲一個例子

我想編輯分配給票的用戶。首先,我從我的表中選擇值,然後將其分解並列出用戶。現在,如果這些用戶仍然是Active Directory的一部分並且擁有足夠的權限,那麼現在我需要將它們結合起來並在更新數據庫之前進行檢查。

  1. SELECT從數據庫
  2. 爆炸,顯示
  3. 綁定到LDAP顯示所有其他用戶
  4. 檢查,如果用戶仍然存在並有LDAP權利
  5. 結合用戶
  6. 更新數據庫

謝謝你這麼多你的時間:)


我最終什麼了:

爲了方便起見我有這樣的:

if(!isset($_SESSION["DN"]) && !isset($_SESSION["username"])): 
    // connect to ldap 
    $ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server."); 
    // binding to ldap server 
    ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn)); 

    // search for $filter 
    $result = ldap_search($ldapconn, LDAP_TREE, '(sAMAccountName='.USER.')') or die("Error in search query: " . ldap_error($ldapconn)); 
    $data = ldap_get_entries($ldapconn, $result); 
    utf8_encoder($data); 
    ldap_close($ldapconn); 
    $_SESSION["DN"] = $data[0]["dn"]; 
    preg_match('/^CN=(.+?),(?:CN|OU)=.+/', $_SESSION['DN'], $matches); 
    $_SESSION["username"] = $matches[1]; 
endif; 

如果我需要顯示我有這樣的用戶:

// connect to ldap 
$ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server."); 
// binding to ldap server 
ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn)); 

?>  
<div id="container"> 
    <form action="#" method="post"> 
    <table> 
     <tbody> 
     <?php 

echo "<tr><td>Repairgroup</td></tr>"; 

$result = ldap_read($ldapconn, 
    "CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=domain,DC=local", 
    "(objectClass=*)", 
    ["member"] 
); 
$data = ldap_get_entries($ldapconn, $result); 
utf8_encoder($data); 

foreach($data[0]["member"] as $k => $v): 
    if(!is_int($v)): 
     preg_match('/^CN=(.+?),(?:CN|OU)=.+/', $v, $name); 
     echo "<tr><td><label class=\"label\"><input type=\"checkbox\" name=\"user[]\" value=\"".$v."\" />".$name[1]."</label></td></tr>\n"; 
    endif; 
endforeach; 
?> 
    </tbody> 
</table> 
</form> 

然後,我會在我的數據庫中存儲一個或多個DN,與|分開d後,當我不得不只顯示我用這個名字:

preg_match_all('/\bCN=\b(.+?),/', $row->iduser, $name, PREG_SET_ORDER, 0); 
echo "<td class=\"worker\"><span>"; 
for($i = 0; $i < count($name); $i++): 
    echo "<p>".$name[$i][1]."</p>\n"; 
endfor; 
echo "</span></td>\n"; 

這是我的正則表達式的一個例子:https://regex101.com/r/s6PbOR/1/

,並檢查是否有人訪問:

if(is_allowed($_SESSION["DN"], 'CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local')): 
    display some data 
endif; 

謝謝你Esteban引導我走向這個! :)非常感謝

回答

1
  • ,請問有什麼我可以在我的代碼或使用LDAP的方式提高?
  • 我是否正確地使用LDAP? (我知道答案將根據意見,但只要我不跟我的代碼濫用LDAP我與它的罰款我猜)

你用你的LDAP目錄作爲一個後端RDBM。您應該嘗試按預期使用它:分層數據庫。

在你的代碼:

  1. 請求具有屬性memberof集爲一組
  2. 檢查是否USER是該組

的一部分,但每個用戶:你有組DN,LDAP具有委託用戶成爲組的一部分的機制,該組應該存在於該目錄中。

SO:我可能做的就是:

檢索member屬性組:

$result = ldap_read($ldapconn, 
"CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local", 
"(objectClass=*)", 
["member"] 
) 

這樣可以節省你搜索到該目錄中的負載,因爲你直接訪問該條目提供唯一的ID讀(DN)

  • 如何保存會是綁定到每次LDAP相比,只是有我的數據庫中的用戶?
  • 如果不安全使用LDAP,我應該每天運行一次某些腳本向用戶填充表格?

LDAP是被用來處理一個比多讀的更高的協議/搜索比寫,所以只要請求/搜索被優化,應該沒有問題尋找一個用戶每你需要它的時候。

  • 更簡單的方法,像下面執行的東西嗎?
  • 而是在售票臺存儲用戶的一些顯示名稱的我會存儲用戶的DN。它有2個好處
    • 允許你ldap_read用戶條目,而無需進行搜索,找到此信息事先
    • 的爆炸,你會從你的數據庫獲得陣列照片直接進行比較與member屬性返回數組由ldap_read上的LDAP基(如前所示)
  • 檢查是否用戶仍然呈現:
    • 這將是存在於在使用者該組的屬性應該存在於該目錄中,因此您需要檢查的列表僅爲數據庫中存在的列表,並且不在組中
    • 如果不應將它們分配給票據,因爲它們不在組,那麼就沒有再檢查存在,否則你只需要ldap_read用戶進入而不檢索任何屬性,如果用戶不存在,你將有一個LDAP錯誤:32 no such object

它將比進行多次搜索要快得多,效率更高

如果你做這種方式,來檢查,如果用戶存在一個組中,並且被允許,你發佈的代碼只會是:

// USER would be the DN in this case 
if(is_allowed(USER, 'CN=Repairgroup,OU=Laboratory,OU=Organization,OU=MyBusiness,DC=somedc,DC=local')): 
    display some data 
endif; 

function is_allowed($check, $dn) { 
    // connect to ldap 
    $ldapconn = ldap_connect(LDAP_HOST) or die("Could not connect to LDAP server."); 
    // binding to ldap server 
    ldap_bind($ldapconn, LDAP_USER, LDAP_PASS) or die("Error trying to bind: " . ldap_error($ldapconn)); 

    // search for $dn 
    $result = ldap_read($ldapconn, 
    $dn, 
    "(objectClass=*)", 
    ["member"] 
    ) or die("Error in search query: " . ldap_error($ldapconn)); 
    $data = ldap_get_entries($ldapconn, $result); 
    ldap_close($ldapconn); 

    return in_array($check, $data[0]['member']); 
} 

(注意:您將需要調整這個有點處理由用戶從LDAP目錄中刪除的錯誤代碼返回)

+0

首先感謝你的回答!我正在研究它,這非常有幫助。然而,我有兩個關於你的解決方案的問題:** 1。**你如何將DN輸入數據庫? *我的想法是存儲DN並將其分隔爲「|'」。要顯示名稱,它應該足以提取CN = Name Lastname並顯示它,而不是再次執行ldap_read。* ** 2。**當您說錯誤代碼返回時,請您談談Error 32 no such object'? – floGalen

+0

我正在閱讀[分層數據庫模型](https://en.wikipedia.org/wiki/Hierarchical_database_model)和[關係數據庫管理系統](https://en.wikipedia.org/wiki/Relational_database_management_system)在你的答案中給出的關鍵字找到了用ldap查看php中用戶管理的詳細信息。 https://stackoverflow.com/a/28787550/8188398或https://www.null-byte.org/development/php-active-directory-ldap-authentication/以及http://www.tldp.org/ HOWTO/LDAP-HOWTO /這極大地改進了我對LDAP的使用以及我對事物工作方式的理解。再次感謝! – floGalen

+0

@floGalen要存儲DN,取決於你要使用什麼樣的語言,因爲DN中沒有無效字符(有些需要轉義),所以如果系統上的更多指南不使用你的DN中的分隔符,而不是所有LDAP DN通用的絕對規則。對於你的第二點,是的,我談到了「錯誤32」。這只是從內存中,所以我不知道如果一個非現有的DN上的'ldap_read'會返回一個錯誤或一個空的結果,所以萬一它是錯誤,你必須處理它,而不是做一個'死'劇本。 – Esteban

相關問題