PageRenderTime 24ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Library/Kumbia/Auth/Auth.php

http://kumbia-enterprise.googlecode.com/
PHP | 389 lines | 184 code | 29 blank | 176 comment | 33 complexity | f39c4476b6f8b35ac02564e840ff0643 MD5 | raw file
  1. <?php
  2. /**
  3. * Kumbia Enterprise Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the New BSD License that is bundled
  8. * with this package in the file docs/LICENSE.txt.
  9. *
  10. * If you did not receive a copy of the license and are unable to
  11. * obtain it through the world-wide-web, please send an email
  12. * to license@loudertechnology.com so we can send you a copy immediately.
  13. *
  14. * @category Kumbia
  15. * @package Auth
  16. * @copyright Copyright (c) 2008-2009 Louder Technology COL. (http://www.loudertechnology.com)
  17. * @copyright Copyright (c) 2005-2008 Andres Felipe Gutierrez (gutierrezandresfelipe at gmail.com)
  18. * @license New BSD License
  19. * @version $Id: Auth.php 103 2009-10-09 01:30:42Z gutierrezandresfelipe $
  20. */
  21. /**
  22. * Auth
  23. *
  24. * Componente que permite realizar autenticacion sobre multiples
  25. * gestores de identidad, directorios, PAM, etc.
  26. *
  27. * @category Kumbia
  28. * @package Auth
  29. * @copyright Copyright (c) 2008-2009 Louder Technology COL. (http://www.loudertechnology.com)
  30. * @copyright Copyright (c) 2005-2008 Andres Felipe Gutierrez (gutierrezandresfelipe at gmail.com)
  31. * @license New BSD License
  32. */
  33. class Auth extends Object {
  34. /**
  35. * Nombre del adaptador usado para autenticar
  36. *
  37. * @var string
  38. */
  39. private $_adapter;
  40. /**
  41. * Objeto Adaptador actual
  42. *
  43. * @var mixed
  44. */
  45. private $_adapterObject = null;
  46. /**
  47. * Indica si un usuario debe loguearse solo una vez en el sistema desde
  48. * cualquier parte
  49. *
  50. * @var boolean
  51. */
  52. private $_activeSession = false;
  53. /**
  54. * Tiempo en que expirara la sesion en caso de que no se termine con destroyActiveSession
  55. *
  56. * @var integer
  57. */
  58. private $_expireTime = 3600;
  59. /**
  60. * Argumentos extra enviados al Adaptador
  61. *
  62. * @var array
  63. */
  64. private $_extraArgs = array();
  65. /**
  66. * Tiempo que duerme la aplicacion cuando falla la autenticacion
  67. */
  68. private $_sleepTime = 0;
  69. /**
  70. * Indica si el ultimo llamado a authenticate tuvo exito o no (persistente en sesion)
  71. *
  72. * @var boolean
  73. */
  74. static private $_isValid = null;
  75. /**
  76. * Ultima identidad obtenida por Authenticate (persistente en sesion)
  77. *
  78. * @var array
  79. */
  80. static private $_activeIdentity = array();
  81. /**
  82. * Adaptadores Soportados
  83. *
  84. * @var array
  85. */
  86. static private $_supportedAdapters = array('digest', 'http', 'model', 'kerberos5', 'radius', 'ldap');
  87. /**
  88. * Constructor del Autenticador
  89. *
  90. * @access public
  91. */
  92. public function __construct(){
  93. $numberArguments = func_num_args();
  94. $extraArgs = Utils::getParams(func_get_args(), $numberArguments);
  95. if(isset($extraArgs[0])){
  96. $adapter = $extraArgs[0];
  97. unset($extraArgs[0]);
  98. } else {
  99. if(isset($extraArgs['adapter'])){
  100. $adapter = $extraArgs['adapter'];
  101. } else {
  102. $adapter = 'model';
  103. }
  104. }
  105. $this->setAdapter($adapter, $this, $extraArgs);
  106. }
  107. /**
  108. * Establece el Adaptador a ser utilizado
  109. *
  110. * @access public
  111. * @param string $adapter
  112. * @param string $auth
  113. * @param string $extraArgs
  114. */
  115. public function setAdapter($adapter, $auth = null, $extraArgs=array()){
  116. if(!in_array($adapter, self::$_supportedAdapters)){
  117. throw new AuthException('Adaptador de autenticación "'.$adapter.'" no soportado');
  118. }
  119. $this->_adapter = $adapter;
  120. $adapterClass = $adapter.'Auth';
  121. if(class_exists($adapterClass, false)==false){
  122. $filePath = 'Library/Kumbia/Auth/Adapters/'.ucfirst($adapter).'.php';
  123. if(Core::fileExists($filePath)){
  124. /**
  125. * @see AuthInterface
  126. */
  127. require 'Library/Kumbia/Auth/Interface.php';
  128. require 'Library/Kumbia/Auth/Adapters/'.ucfirst($adapter).'.php';
  129. } else {
  130. throw new AuthException("No existe el adaptador de autenticación: '$adapter'");
  131. }
  132. }
  133. $this->_extraArgs = $extraArgs;
  134. $this->_adapterObject = new $adapterClass($auth, $extraArgs);
  135. }
  136. /**
  137. * Obtiene el nombre del adaptador actual
  138. *
  139. * @access public
  140. * @return boolean
  141. */
  142. public function getAdapterName(){
  143. return $this->_adapter;
  144. }
  145. /**
  146. * Realiza el proceso de autenticación
  147. *
  148. * @access public
  149. * @return array
  150. */
  151. public function authenticate(){
  152. $result = $this->_adapterObject->authenticate();
  153. /**
  154. * Si es una sesion activa maneja un archivo persistente para control
  155. */
  156. if($result&&$this->_activeSession){
  157. $activeApp = Router::getApplication();
  158. $userHash = md5(serialize($this->_extraArgs));
  159. $filename = "cache/".base64_encode($activeApp);
  160. if(Core::fileExists($filename)){
  161. $fp = fopen($filename, "r");
  162. while(!feof($fp)){
  163. $line = fgets($fp);
  164. $user = explode(":", $line);
  165. if($userHash==$user[0]){
  166. if($user[1]+$user[2]>time()){
  167. if($this->sleepTime){
  168. sleep($this->sleepTime);
  169. }
  170. self::$_identity = array();
  171. self::$_isValid = false;
  172. return false;
  173. } else {
  174. fclose($fp);
  175. $this->_destroyActiveSession();
  176. file_put_contents($filename, $userHash.":".time().":".$this->expireTime."\n");
  177. }
  178. }
  179. }
  180. fclose($fp);
  181. $fp = fopen($filename, "a");
  182. fputs($fp, $userHash.":".time().":".$this->_expireTime."\n");
  183. fclose($fp);
  184. } else {
  185. file_put_contents($filename, $userHash.":".time().":".$this->_expireTime."\n");
  186. }
  187. }
  188. if(!$result){
  189. if($this->_sleepTime){
  190. sleep($this->_sleepTime);
  191. }
  192. }
  193. Session::set('AUTH_IDENTITY', $this->_adapterObject->getIdentity());
  194. self::$_activeIdentity = $this->_adapterObject->getIdentity();
  195. Session::set('AUTH_VALID', $result);
  196. self::$_isValid = $result;
  197. return $result;
  198. }
  199. /**
  200. * Realiza el proceso de autenticación usando HTTP
  201. *
  202. * @access public
  203. * @return array
  204. */
  205. public function authenticateWithHttp(){
  206. if(!$_SERVER['PHP_AUTH_USER']){
  207. header('WWW-Authenticate: Basic realm="basic"');
  208. header('HTTP/1.0 401 Unauthorized');
  209. return false;
  210. } else {
  211. $options = array('username' => $_SERVER['PHP_AUTH_USER'], 'password' => $_SERVER['PHP_AUTH_PW']);
  212. $this->_adapterObject->setParams($options);
  213. return $this->authenticate();
  214. }
  215. }
  216. /**
  217. * Devuelve la identidad encontrada en caso de exito
  218. *
  219. * @access public
  220. * @return array
  221. */
  222. public function getIdentity(){
  223. return $this->_adapterObject->getIdentity();
  224. }
  225. /**
  226. * Permite controlar que usuario no se loguee mas de una vez en el sistema desde cualquier parte
  227. *
  228. * @access public
  229. * @param string $value
  230. * @param integer $time
  231. */
  232. public function setActiveSession($value, $time=3600){
  233. $this->_activeSession = $value;
  234. $this->_expireTime = $time;
  235. }
  236. /**
  237. * Permite saber si existe una identidad en la sesion actual
  238. *
  239. * @access public
  240. */
  241. public function existsIdentity(){
  242. if(Session::issetData('AUTH_IDENTITY')==true){
  243. if(is_array(Session::getData('AUTH_IDENTITY'))){
  244. return true;
  245. } else {
  246. return false;
  247. }
  248. } else {
  249. return false;
  250. }
  251. }
  252. /**
  253. * Destruir sesion activa del usuario autenticado
  254. *
  255. */
  256. public function destroyActiveSession(){
  257. $activeApp = Router::getApplication();
  258. $userHash = md5(serialize($this->_extraArgs));
  259. $filename = "cache/".base64_encode($activeApp);
  260. $lines = file($filename);
  261. $linesOut = array();
  262. foreach($lines as $line){
  263. if(substr($line, 0, 32)!=$userHash){
  264. $linesOut[] = $line;
  265. }
  266. }
  267. file_put_contents($filename, join("\n", $linesOut));
  268. }
  269. /**
  270. * Devuelve la instancia del adaptador
  271. *
  272. * @return string
  273. */
  274. public function getAdapterInstance(){
  275. return $this->_adapterObject;
  276. }
  277. /**
  278. * Determinar si debe dormir la aplicacion cuando falle la autenticación y cuanto tiempo en segundos
  279. *
  280. * @param boolean $value
  281. * @param integer $time
  282. */
  283. public function sleepOnFail($value, $time=2){
  284. $time = (int) $time;
  285. if($time<0){
  286. $time = 0;
  287. }
  288. if($value){
  289. $this->_sleepTime = $time;
  290. } else {
  291. $this->_sleepTime = 0;
  292. }
  293. }
  294. /**
  295. * Devuelve el resultado del uttimo llamado a authenticate desde el ultimo objeto Auth instanciado
  296. *
  297. * @return boolean
  298. * @static
  299. */
  300. static public function isValid(){
  301. if(self::$_isValid!==null){
  302. return self::$_isValid;
  303. } else {
  304. self::$_isValid = Session::get('AUTH_VALID');
  305. return self::$_isValid;
  306. }
  307. }
  308. /**
  309. * Establece el tiempo en que debe expirar la sesion
  310. *
  311. * @param int $time
  312. */
  313. public function setExpireTime($time){
  314. Session::set('AUTH_EXPIRE', (int)$time);
  315. Session::set('AUTH_TIME', Core::getProximityTime());
  316. }
  317. /**
  318. * Devuelve el resultado de la ultima identidad obtenida en authenticate desde el ultimo objeto Auth instanciado
  319. *
  320. * @access public
  321. * @return array
  322. * @static
  323. */
  324. static public function getActiveIdentity(){
  325. if(count(self::$_activeIdentity)){
  326. return self::$_activeIdentity;
  327. } else {
  328. self::$_activeIdentity = Session::get('AUTH_IDENTITY');
  329. return self::$_activeIdentity;
  330. }
  331. }
  332. /**
  333. * Establece programacionalmente la identidad actual
  334. *
  335. * @access public
  336. * @param array $identity
  337. * @static
  338. */
  339. static public function setActiveIdentity($identity){
  340. if(is_array($identity)||is_object($identity)){
  341. Session::set('AUTH_IDENTITY', $identity);
  342. self::$_activeIdentity = $identity;
  343. Session::set('AUTH_VALID', true);
  344. } else {
  345. throw new AuthException('La identidad debe ser una variable array ó un objeto');
  346. }
  347. }
  348. /**
  349. * Anula la identidad actual
  350. *
  351. * @access public
  352. * @static
  353. */
  354. static public function destroyIdentity(){
  355. self::$_isValid = null;
  356. Session::unsetData('AUTH_VALID');
  357. self::$_activeIdentity = null;
  358. Session::unsetData('AUTH_IDENTITY');
  359. }
  360. }