问题
I have a question regarding user membership of groups in Active directory and grabbing such memberships with PHP. My big question/situation is that I have a site I am making and essentially I am trying to assign administrators based off of groups in Active directory and I know how to check member of status on an account but my problem is that there are some groups that aren't displayed there, and one of the groups that is not displayed is the group I need. Is there a way I can check who is a member of that group instead of checking if that user is a member of that group. Alternatively if someone knows why certain groups are not appearing in my search I would prefer to search membership that way because then it would be a simple logic statement to check if the user is in that group, my code is below and it does work but as I said there are certain groups that don't appear and I think I read somewhere about how membership is stored and also if it is a direct membership or if you are a member of a group that is a member of another group. One group that we use as our default group is Domain users but no one has that in there memberOf array even though that group's membership is direct as in the members of that group are all users not other security groups containing the users.
At some point in this program I need to mark certain users as "managers" and the easiest way for me to do so would be to store a flag VIA session variable if they are a member of a certain manager group, as stated above the problem I am running into is users are not appearing in some of their groups so this isn't working, the group that would give access to managers is not appearing in my MemberOf area. During the final stage I will have to go through 5-6 groups and add all the members to the database, it is a similar problem and should have a similar solution so maybe I can kill two birds with 1 stone if I figure that one out too. What I mean by this problem is that I will need to grab a group such as something like 'users HR' and then upload them all to the database by givenname and surname and some default values for other fields but I don't know how to grab users from a group, I know how to grab groups of a user but even that doesn't grab 100% of the groups and if I can reverse that order and act as the group and check my own members that would make things real easy, our current application that we are using to do all this for us is in ASP.net but 10 years old or so and has an administrator account hard coded in to access groups and so on, even doing that I still am not sure how I would get members of a group.
Code:
<?php
$ldap = ldap_connect("192.168.1.**");
$ldap_dn = "DC=************,DC=local";
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
$access = NULL;
if ($bind = ldap_bind($ldap, "***********\\" . $_POST['username'], $_POST['password'])) {
$filter = "(sAMAccountName=" . $_POST['username'] . ")";
$attr = array("memberof","givenname","sn","mail");
$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
$entries = ldap_get_entries($ldap, $result);
$givenname = $entries[0]['givenname'][0] . " " . $entries[0]['sn'][0];
ldap_unbind($ldap);
//var_dump($entries[0]["sn"][0]);
//var_dump($givenname);
//var_dump($entries[0]);
// check groups
foreach($entries[0]['memberof'] as $grps) {
// is manager, break loop
//if (strpos($grps, $ldap_manager_group)) { $access = 2; break; }
// is user
//var_dump($grps);
if (strpos($grps, "****** * *** *****")) $access = "****** *";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
}
if ($access != NULL) {
// establish session variables
$_SESSION['user'] = $_POST['username'];
$_SESSION['access'] = $access;
$_SESSION['givenname'] = $givenname;
$_SESSION['email'] = $entries[0]['mail'][0];
return true;
} else {
//echo "No rights?";
// user has no rights
return false;
}
} else {
//header("Location: login.php?Error=Invalid Identity");
echo "Elese Here";
}
?>
Edit:
I have been trying to use this tutorial: samjlevy.com and I understand it for the most part but I am getting a few errors:
Warning: ldap_search(): Search: Operations error in C:\inetpub\wwwroot\InOutBoard\test.php on line 62
Warning: ldap_get_entries() expects parameter 2 to be resource, boolean given in C:\inetpub\wwwroot\InOutBoard\test.php on line 63
Warning: array_shift() expects parameter 1 to be array, null given in C:\inetpub\wwwroot\InOutBoard\test.php on line 66
Warning: Invalid argument supplied for foreach() in C:\inetpub\wwwroot\InOutBoard\test.php on line 72
Array ( )
They all seem to be with the search because it isn't working it's return a NULL set to result which isn't going to allow other parts to run. I am not sure if my $ldap_dn is correct as I am using the same one from the php code above. My layout is as follows (I am new to this I believe this is correct): DC=company,DC=local and so it should be for the group I want: CN=Group Looking For,OU=lowestLevel Ou,OU=Groups,OU=company,DC=Company,DC=local
Would I have to use that as my $ldap_dn?
EDIT 2: (Updated Code)
This code is displaying all the groups that a user is in and works very well, is there a way to write a second page that uses a similar page to take one of those groups and grabs all the members out of it?
<?php
$ldap = ldap_connect("192.168.1.**");
$ldap_dn = "DC=Company,DC=local";
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option( $ldap, LDAP_OPT_PROTOCOL_VERSION, 3 );
$access = NULL;
if ($bind = ldap_bind($ldap, "**********\\" . $_POST['username'], $_POST['password'])) {
$filter = "(sAMAccountName=" . $_POST['username'] . ")";
$attr = array("memberof","givenname","sn","mail","distinguishedname");
$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
$entries = ldap_get_entries($ldap, $result);
$givenname = $entries[0]['givenname'][0] . " " . $entries[0]['sn'][0];
//ldap_unbind($ldap);
//var_dump($entries[0]["sn"][0]);
//var_dump($givenname);
//var_dump($entries[0]);
var_dump($entries[0]['distinguishedname'][0]);
$gFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=".$entries[0]['distinguishedname'][0]."))";
$gAttr = array("cn");
$result1 = ldap_search($ldap, $ldap_dn, $gFilter, $gAttr) or exit("Unable to search LDAP server");
$groups = ldap_get_entries($ldap, $result1);
var_dump($groups);
// check groups
foreach($entries[0]['memberof'] as $grps) {
// is manager, break loop
//if (strpos($grps, $ldap_manager_group)) { $access = 2; break; }
// is user
//var_dump($grps);
if (strpos($grps, "****** * *** *****")) $access = "****** *";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
if (strpos($grps, "*** Group")) $access = "***";
if (strpos($grps, "***")) $access = "***";
}
if ($access != NULL) {
// establish session variables
$_SESSION['user'] = $_POST['username'];
$_SESSION['access'] = $access;
$_SESSION['givenname'] = $givenname;
$_SESSION['email'] = $entries[0]['mail'][0];
return true;
} else {
//echo "No rights?";
// user has no rights
return false;
}
} else {
//header("Location: login.php?Error=Invalid Identity");
echo "Elese Here";
}
?>
Second Page: This page is supposed to find members of a group which looks like it may be trying to do so but not picking out members of groups but one of our OU's instead. Look below to code for a layout and what it's grabbing.
<?php
function get_members($group=FALSE,$inclusive=FALSE) {
$ldap_host = "192.168.1.***";
$ldap_dn = "OU=******,OU=*****,OU=**********,DC=Company,DC=local";
$ldap_usr_dom = "@".$ldap_host;
$user = "*******";
$password = "******";
$keep = array(
"samaccountname",
"distinguishedname"
);
$ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP");
ldap_bind($ldap, "REGION5SYSTEMS\\" . $user, $password) or die("Could not bind to LDAP");ry
if($group) $query = "(&"; else $query = "";
$query .= "(&(objectClass=user)(objectCategory=person))";
if(is_array($group)) {
// Looking for a members amongst multiple groups
if($inclusive) {
$query .= "(|";
} else {
$query .= "(&";
}
foreach($group as $g) $query .= "(memberOf=CN=$g,$ldap_dn)";
$query .= ")";
} elseif($group) {
$query .= "(memberOf=CN=$group,$ldap_dn)";
}
if($group) $query .= ")"; else $query .= "";
$results = ldap_search($ldap,$ldap_dn,$query);
$entries = ldap_get_entries($ldap, $results);
array_shift($entries);
$output = array(); // Declare the output array
$i = 0; // Counter
// Build output array
foreach($entries as $u) {
foreach($keep as $x) {
// Check for attribute
if(isset($u[$x][0])) $attrval = $u[$x][0]; else $attrval = NULL;
$output[$i][$x] = $attrval;
}
$i++;
}
return $output;
}
// Example Output
print_r(get_members()); // Gets all users in 'Users'
print_r(get_members("Group I'm search for")); // Gets all members of 'Test Group'
?>
So our DC is DC=CompanyName,DC=Local and we then have folders and OU's and One of the OU's is named 'CompanyName' and nested in it are OU's such as Admins Computers, Contacts, Groups, ect ect... The OU I am looking at is Users and nested within that are different organizations in our building (They use our domian) and one extra OU that is made for this project. Background on the project is a employee inoutBoard and so we have 3 Security groups in that OU, one for other organization's members, one for our organizations members and one for those who are managers from both our Org and their org, basically people who can change status's of others if they forget to do so. What we would ideally want to do is have some sort of sync button which could go check members of those groups and then upload them to the database as well as some default values such as default status of out of office and no description or anything like that. Those groups do not contain people either, they contain other security groups. That's what we want to work, we want to be able to find the members of those groups, the second bit a code I attached will work sometimes, if I set $ldap_dn to "CN=Company,DC=Company,DC=Local" it will print all users in the Users OU and then go into all the OU's there and print the users from those OU's except the OU that we actually need which is that OU that has the groups for the in out board. If I specify that path as the $ldap_dn it just prints array() and nothing else. Any Idea?
回答1:
The memberOf
attribute will only contain direct group memberships, so recursive memberships will not be listed. However, you could specifically query for the recursive group memberships of a user like so (to adapt your code a bit directly after the bind):
$filter = "(sAMAccountName=" . $_POST['username'] . ")";
$attr = array("givenname","sn","mail", "distinguishedname");
$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
$entries = ldap_get_entries($ldap, $result);
$gFilter = "(&(objectClass=group)(member:1.2.840.113556.1.4.1941:=".$entries[0]['distinguishedname'][0]."))";
$gAttr = array("cn");
$result = ldap_search($ldap, $ldap_dn, $gFilter, $gAttr) or exit("Unable to search LDAP server");
$groups = ldap_get_entries($ldap, $result);
Not tested at the moment, but that is the general filter and process for doing it. Get the DN of the user then use the matching rule OID 1.2.840.113556.1.4.1941
to get groups recursively.
The reason you are not getting the "Domain Users" group to show up is because that is a "special" primary group in AD, stored within the primaryGroupId
attribute of a user. Additional info on that here:
https://support.microsoft.com/en-us/kb/297951
来源:https://stackoverflow.com/questions/36920534/ldap-finding-members-of-a-group-php