跟小D每日学口语

simple-LDAP-auth

  1 <?php
  2 /**
  3  * simple class for LDAP authentification
  4  * 
  5  Copyright (C) 2013 Petr Palas
  6 
  7 This program is free software; you can redistribute it and/or
  8 modify it under the terms of the GNU General Public License
  9 as published by the Free Software Foundation; either version 2
 10 of the License, or (at your option) any later version.
 11 
 12 This program is distributed in the hope that it will be useful,
 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15 GNU General Public License for more details.
 16 
 17 You should have received a copy of the GNU General Public License
 18 along with this program; if not, write to the Free Software
 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 20  * inspired by http://samjlevy.com/2010/09/php-login-script-using-ldap-verify-group-membership/
 21  */ 
 22 
 23 namespace LDAP;
 24 
 25 use Exception;
 26 
 27 class auth {
 28     /**
 29      * url or ip of ldap server
 30      * @var type string
 31      */
 32     protected $ldap_host;
 33     /**
 34      * active directory DN
 35      * @var type string
 36      */
 37     protected $ldap_dn;
 38     /**
 39      * target user group
 40      * @var type string
 41      */
 42     protected $ldap_user_group;
 43     /**
 44      * manager group (shud contain users with management access)
 45      * @var type string
 46      */
 47     protected $ldap_manager_group;
 48     /**
 49      * contains email domain like "@somedomain.com"
 50      * @var type string
 51      */
 52     protected $ldap_usr_dom;
 53     
 54     /**
 55      * countains connection resource
 56      * @var type resource
 57      */
 58     protected $ldap;
 59     
 60     /**
 61      * contains status text
 62      * if exeption is thrown msg contains this string
 63      * @var type string
 64      */
 65     public $status;
 66     /**
 67      * contains result array if ldap_search is succesfull
 68      * @var type array
 69      */
 70     public $result;
 71     /**
 72      * contains auth state 0=unathrized 1=authorized
 73      * @var type int
 74      */
 75     public $auth=0;
 76     /**
 77      * contains access level 0=none or unathorized 1=user 2=managment acc
 78      * @var type int
 79      */
 80     public $access=0;
 81     
 82     /**
 83      * contains username after user init
 84      * @var type string
 85      */
 86     public $user;
 87     
 88     /**
 89      * contain user password after user init
 90      * @var type string
 91      */
 92     protected $password;
 93     
 94     /**
 95      * Exeptions code constants
 96      */
 97     const ERROR_WRONG_USER_GROUP=2;
 98     const ERROR_CANT_AUTH=1;
 99     const ERROR_CANT_SEARCH=3;
100     const ERROR_IMG_DECODE=4;
101     const ERROR_CANT_CONNECT=5;
102 
103     /**
104      * loads passed configuration in case of the ldap_usr_dom it makes sure that this strings begins with '@' 
105      * @param type $ldap_host
106      * @param type $ldap_dn
107      * @param type $ldap_user_group
108      * @param type $ldap_manager_group
109      * @param type $ldap_usr_dom
110      */
111     function __construct($ldap_host,$ldap_dn,$ldap_user_group,$ldap_manager_group,$ldap_usr_dom) {
112         $this->ldap_host=$ldap_host;
113         $this->ldap_dn=$ldap_dn;
114         $this->ldap_user_group=$ldap_user_group;
115         $this->ldap_manager_group=$ldap_manager_group;
116         $this->ldap_usr_dom=  '@'.trim($ldap_usr_dom,'@');
117     }
118     
119     /**
120      * well destructor :P
121      * just in case there is opened connection to LDAP while destructing this class
122      */
123     public function __destruct() {
124         @ldap_unbind($this->ldap);
125     }
126     
127     /**
128      * dumps result array for debug enclosed in pre tag
129      * Wont terminate script!
130      */
131     public function dump_resut() {
132         echo '<pre>';
133         print_r($this->result,FALSE);
134         echo '</pre>';
135     }
136     
137     /**
138      * Inits connection to LDAP server throws exeption on failure
139      * @return boolean
140      * @throws Exception
141      */
142     protected function init_connection(){
143         $this->ldap=ldap_connect($this->ldap_host,3268);
144         if($this->ldap){
145             $this->status='connected :)';
146             ldap_set_option($this->ldap, LDAP_OPT_PROTOCOL_VERSION,3);
147             ldap_set_option($this->ldap, LDAP_OPT_REFERRALS,0);
148         }
149         else {
150             //TODO: PHP actualy dont check if there is LDAP present on the other end nor it will fail if target host is unreachable. So I need some work around that :(
151             $this->status='Cant connect to LDAP';
152             throw new Exception($this->status,  self::ERROR_CANT_CONNECT);
153         }
154         return TRUE;
155     }
156     
157     public function userInit($user,$password) {
158         $this->user=$user;
159         $this->password=$password;
160         
161         return TRUE;
162     }
163     
164     /**
165      * Converts Binary string (like thumbnail from LDAP to base64 datastring for display
166      * @param type $file
167      * @param type $mime
168      * @return type base64 datastring
169      */
170     protected function data_uri($file, $mime) {  
171       $base64   = base64_encode($file); 
172       return ('data:' . $mime . ';base64,' . $base64);
173     }
174     
175     /**
176      * Gets LDAP thumbnail img
177      * @param type $user
178      * @param type $password
179      * @param type $raw if TRUE method will return raw binary string instead of base64 encoded with mime
180      * @return type base64 datatring of the thumbnail
181      * @throws Exception
182      */
183     public function getLDAPimg($user=null,$password=null,$raw=FALSE) {
184         $this->refreshCredentials($user, $password);
185         //since conection is one off we need to get it
186         $this->init_connection();
187         
188         $bind = @ldap_bind($this->ldap, $user . $this->ldap_usr_dom, $password);//ldap_bind($this->ldap, $this->ldap_dn, $password);
189         
190         if($bind){
191             $filter = "(sAMAccountName=" . $user . ")";
192             $attr = array("thumbnailphoto");
193             $result = @ldap_search($this->ldap, $this->ldap_dn, $filter, $attr);
194             if($result==FALSE){
195                 throw new Exception("Unable to search LDAP server. Reason: ".  ldap_error($this->ldap),  self::ERROR_CANT_SEARCH);
196             }  
197             $entry= ldap_first_entry($this->ldap, $result);
198 
199             if ($entry) {
200                 $info = @ldap_get_values_len($this->ldap, $entry, "thumbnailphoto");
201                 if(!$info){
202                    throw new Exception("Unable to decode thumbnail. Error: ".  ldap_error($this->ldap),  self::ERROR_IMG_DECODE);
203                 }
204                 //echo '<img src="'.$this->data_uri($info[0], 'image/png').'">';
205             }
206             
207             
208             if(!$raw){
209                 return $this->data_uri($info[0], 'image/png');
210             }
211             else{
212                 return $info[0];
213             }
214         }
215         else {
216             // invalid name or password
217             $this->status='Cant authenticate for search on LDAP';
218             throw new Exception($this->status.' '.  ldap_error($this->ldap), self::ERROR_CANT_AUTH);
219         }
220         ldap_unbind($this->ldap);
221     }
222     
223     /**
224      * Tries to authenticate suplied user with suplied pass
225      * @param type $user
226      * @param type $password
227      * @return boolean
228      * @throws Exception
229      */
230     public function authenticate($user=null, $password=null) {
231        $this->refreshCredentials($user, $password);
232         //since conection is one off we need to get it
233         $this->init_connection();
234         
235         // verify user and password
236         $bind = @ldap_bind($this->ldap, $user . $this->ldap_usr_dom, $password);
237 
238         
239         if($bind) {
240             // valid
241             // check presence in groups
242             $filter = "(sAMAccountName=" . $user . ")";
243             $attr = array("memberof");
244             $result = @ldap_search($this->ldap, $this->ldap_dn, $filter, $attr);
245             if($result==FALSE){
246                  throw new Exception("Unable to search LDAP server. Reason: ".  ldap_error($this->ldap),  self::ERROR_CANT_SEARCH);
247             }  
248             $entries = ldap_get_entries($this->ldap, $result);
249             
250             //save result for future use
251             $this->result=$entries;
252 
253             
254             
255             $access = 0;
256             
257             // check groups
258             foreach($entries[0]['memberof'] as $grps) {
259                 // is manager, break loop
260                 if (strpos($grps, $this->ldap_manager_group)) { $access = 2; break; }
261 
262                 // is user
263                 if (strpos($grps, $this->ldap_user_group)) $access = 1;
264             }
265 
266             if ($access != 0) {
267                 // establish result vars
268                 
269                 $this->status='Authenticated';
270                 $this->access=$access;
271                 $this->user= $user;
272                 $this->auth=1;
273                 return true;
274             } else {
275                 // user has no rights
276                 $this->access=$access;
277                 $this->user= $user;
278                 $this->auth=1;
279                 $this->status='User exists but not part of the target group';
280                 throw new Exception($this->status.' '.  ldap_error($this->ldap),  self::ERROR_WRONG_USER_GROUP);
281             }
282 
283         } else {
284             // invalid name or password
285             $this->status='Cant authenticate for search on LDAP';
286             throw new Exception($this->status.' '.  ldap_error($this->ldap),  self::ERROR_CANT_AUTH);
287         }
288         ldap_unbind($this->ldap);
289     }
290     
291     /**
292      * Saves new credentials if we got new or sets the old ones into referenced vars
293      * @param type $user Reference to var that shuld contain username or null
294      * @param type $password Reference to var that shuld contain password or null
295      */
296     private function refreshCredentials(&$user,&$password) {
297         $newCredentials=TRUE;
298         //since we cant set those in param def
299         if($password===null){$password=  $this->password;$newCredentials=FALSE;}
300         if($user===null){$user=  $this->user;$newCredentials=FALSE;}
301         //store user pass and name for future use
302         if($newCredentials){$this->userInit($user, $password);}
303     }
304 
305 }

 

posted @ 2014-08-25 18:02  Danny Chen  阅读(657)  评论(0编辑  收藏  举报