authentication : add a REST/HTML authentication class to not reinvent the wheel each time
git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@2232 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
293
authentication.php
Normal file
293
authentication.php
Normal file
@@ -0,0 +1,293 @@
|
||||
<?php
|
||||
/** DomFramework
|
||||
@package domframework
|
||||
@author Dominique Fournier <dominique@fournier38.fr> */
|
||||
|
||||
require_once ("domframework/auth.php");
|
||||
require_once ("domframework/authparams.php");
|
||||
require_once ("domframework/authsession.php");
|
||||
require_once ("domframework/ratelimit.php");
|
||||
require_once ("domframework/ratelimitfile.php");
|
||||
|
||||
/** All the authentication protocol */
|
||||
class authentication
|
||||
{
|
||||
/** The email of the authenticated/nonauthenticated user */
|
||||
//private $email = "anonymous";
|
||||
|
||||
/** The debug of the authentication methods */
|
||||
public $debug = 0;
|
||||
|
||||
/** The route object */
|
||||
private $route;
|
||||
|
||||
/** Number of authentication maximum by minute */
|
||||
public $ratelimitAuth = 3;
|
||||
/** Directory to store the ratelimit files */
|
||||
public $ratelimitDir = "/tmp";
|
||||
|
||||
/** The rest authentication methods. Can be http, session, post.
|
||||
Attention : session case = CSRF ! */
|
||||
public $restMethods = array ("http");
|
||||
/** The html authentication methods. Can be http, session, post */
|
||||
public $htmlMethods = array ("session");
|
||||
/** The authentication methods. Can be ldap, sympa...*/
|
||||
public $authMethods = array ();
|
||||
/** The authentication servers configuration
|
||||
array ("authXXXX"=>array (
|
||||
array ("ldapserver"=>"ldaps://annuaire.grenoble.cnrs.fr",
|
||||
"ldapport"=>636,
|
||||
"ldaptimeout"=>5,
|
||||
"ldapauth"=>"uid=annuaire,ou=people,dc=grenoble,dc=cnrs,dc=fr",
|
||||
"ldappwd"=>";authANNUAIRE2013",
|
||||
"ldapbase"=>"",
|
||||
"ldapfilter"=>"(mail=%s)",
|
||||
"ldapfield"=>"mail",
|
||||
"ldapfiltersearch"=>"(objectClass=inetOrgPerson)"
|
||||
),
|
||||
),
|
||||
);*/
|
||||
public $authServers = array ();
|
||||
|
||||
public function __construct ($route)
|
||||
{
|
||||
$this->route = $route;
|
||||
}
|
||||
|
||||
/* public function email ()
|
||||
{
|
||||
return $this->email;
|
||||
}*/
|
||||
|
||||
/** Disconnect the user */
|
||||
public function logout ()
|
||||
{
|
||||
if ($this->debug) echo "<pre>LOGOUT\n";
|
||||
$authsession = new authsession ();
|
||||
$param = $authsession->getdetails ();
|
||||
if ($this->debug) echo "Logout for '".$param["email"]."'\n";
|
||||
trigger_error ("Logout for '".$param["email"]."'", E_USER_NOTICE);
|
||||
$authsession->logout ();
|
||||
unset ($_SESSION["domframework"]["authentication"]);
|
||||
$_SESSION["domframework"]["authentication"]["message"] =
|
||||
_("You have been logged out");
|
||||
if ($this->debug) echo "Redirect to authentication page";
|
||||
if ($this->debug) $this->route->debug = $this->debug;
|
||||
$this->route->redirect ("/authentication", "");
|
||||
}
|
||||
|
||||
/** Display the login page */
|
||||
public function pageHTML ($url = "")
|
||||
{
|
||||
// If the user is already connected, redirect to the main page of the site
|
||||
$auth = new auth ();
|
||||
$pre = new authparams (array ("session"));
|
||||
if (isset ($_SESSION["domframework"]["authentication"]["message"]))
|
||||
$message = $_SESSION["domframework"]["authentication"]["message"];
|
||||
else
|
||||
$message = "";
|
||||
unset ($_SESSION["domframework"]["authentication"]["message"]);
|
||||
$alreadyAuth = false;
|
||||
if ($pre->email !== "anonymous")
|
||||
$alreadyAuth = $pre->email;
|
||||
echo $auth->pageHTML ($this->route->baseURL(), $message, $url,
|
||||
$alreadyAuth);
|
||||
}
|
||||
|
||||
/** Check the authentication page */
|
||||
public function verifAuthLoginPage ($url = "")
|
||||
{
|
||||
// rate-limit the connections
|
||||
$ratelimiter = new ratelimitfile ();
|
||||
// 3 connections by minutes
|
||||
$ratelimiter->maxEntries = $this->ratelimitAuth;
|
||||
$ratelimiter->storageDir = $this->ratelimitDir;
|
||||
if (isset ($_SERVER["HTTP_X_FORWARDED_FOR"]))
|
||||
$ipClient = $_SERVER["HTTP_X_FORWARDED_FOR"];
|
||||
else
|
||||
$ipClient = $_SERVER["REMOTE_ADDR"];
|
||||
if ($ratelimiter->set ("loggin-$ipClient") === false)
|
||||
{
|
||||
trigger_error ("Ratelimiting for $ipClient", E_USER_WARNING);
|
||||
$_SESSION["domframework"]["authentication"]["message"] =
|
||||
_("Too much connections");
|
||||
if ($url === "")
|
||||
{
|
||||
$this->route->redirect ("/authentication", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->route->redirect ("/authentication/$url", "");
|
||||
}
|
||||
}
|
||||
$authparams = new authparams (array ("post"));
|
||||
$res = $this->verifAuth ($authparams->email, $authparams->password);
|
||||
if (! is_array ($res))
|
||||
{
|
||||
// Authentication error
|
||||
// Redirect to login page after logout
|
||||
trigger_error ("Logging error for '$authparams->email' (HTML) : $res",
|
||||
E_USER_WARNING);
|
||||
$authsession = new authsession ();
|
||||
$authsession->logout ();
|
||||
$baseURL = $this->route->baseURL ();
|
||||
$_SESSION["domframework"]["authentication"]["message"] = $res;
|
||||
// Check the provided URL before using it
|
||||
if ($url === "")
|
||||
{
|
||||
$this->route->redirect ("/authentication", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->route->redirect ("/authentication/$url", "");
|
||||
}
|
||||
}
|
||||
// Login OK : save in SESSION and go to main page
|
||||
trigger_error ("Logging in for '$authparams->email'", E_USER_NOTICE);
|
||||
$session = new authsession ();
|
||||
$session-> savedatas ($authparams->email, $authparams->password,
|
||||
$res["lastname"], $res["firstname"]);
|
||||
if ($url === "")
|
||||
$this->route->redirect ("/", "");
|
||||
else
|
||||
$this->route->redirect ("/$url", "");
|
||||
}
|
||||
|
||||
/** Check all the REST API */
|
||||
public function verifAuthREST ()
|
||||
{
|
||||
$authparams = new authparams ($this->restMethods);
|
||||
$res = array ("email"=>"anonymous", "password"=>"anonymous");
|
||||
if ($authparams->email !== "anonymous" &&
|
||||
$authparams->password !== "anonymous")
|
||||
{
|
||||
if ($this->debug)
|
||||
echo "verifAuth ($authparams->email, $authparams->password)\n";
|
||||
$res = $this->verifAuth ($authparams->email, $authparams->password);
|
||||
}
|
||||
if (! is_array ($res))
|
||||
{
|
||||
trigger_error ("Logging error for '$authparams->email' (REST) : $res",
|
||||
E_USER_WARNING);
|
||||
// Authentication error
|
||||
// TODO : header 401 ? Block previously in the framework auth process
|
||||
exit;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/** Check all the others pages of the site */
|
||||
public function verifAuthHTML ()
|
||||
{
|
||||
if ($this->debug) echo "verifAuthHTML() : ";
|
||||
$authparams = new authparams ($this->htmlMethods);
|
||||
// Don't ask to the provider if anonymous is known
|
||||
if ($authparams->email === "anonymous" || $authparams->email === null)
|
||||
{
|
||||
if ($this->debug) echo "Anonymous\n";
|
||||
return array ("email"=>"anonymous", "lastname"=>"Anonymous",
|
||||
"firstname"=>"", "password"=>"");
|
||||
}
|
||||
if ($this->debug)
|
||||
echo "verifAuth ($authparams->email, $authparams->password)\n";
|
||||
$res = $this->verifAuth ($authparams->email, $authparams->password);
|
||||
if (! is_array ($res))
|
||||
{
|
||||
// Authentication error
|
||||
if ($this->debug) echo "Previous session not found";
|
||||
$msg = _("Previous session not found");
|
||||
$_SESSION["domframework"]["authentication"]["message"] = $msg;
|
||||
trigger_error ("Previous session not found for '$authparams->email'",
|
||||
E_USER_WARNING);
|
||||
$url = $this->route->requestURL();
|
||||
$this->route->redirect ("/authentication/$url");
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/** Do the real authentication process on all the providers defined in the
|
||||
properties of the class.
|
||||
@return an array containing the user datas if the authentication is
|
||||
correct,
|
||||
an exception if noting is found */
|
||||
private function verifAuth ($email, $password)
|
||||
{
|
||||
if (isset ($_SESSION["domframework"]["authentication"]["lastcheck"]) &&
|
||||
$_SESSION["domframework"]["authentication"]["lastcheck"] + 180 <
|
||||
time ())
|
||||
{
|
||||
// Test the authentication each 3 minutes if there is a session, else
|
||||
// return the previous values
|
||||
return $_SESSION["domframework"]["authentication"]["authcache"];
|
||||
}
|
||||
|
||||
foreach ($this->authMethods as $method)
|
||||
{
|
||||
$classname = "auth$method";
|
||||
require_once ("domframework/$classname.php");
|
||||
|
||||
// If only one server is defined, the parameters can directely be pushed
|
||||
// to the classname
|
||||
if (! is_array ($this->authServers[$classname]))
|
||||
{
|
||||
$this->authServers[$classname] = array ($this->authServers[$classname]);
|
||||
}
|
||||
foreach ($this->authServers[$classname] as $key=>$serversParam)
|
||||
{
|
||||
if ($this->debug)
|
||||
echo "Test auth server $method # $classname # $key\n";
|
||||
$authmethod = new $classname ();
|
||||
foreach ($serversParam as $param=>$value)
|
||||
{
|
||||
$authmethod->$param = $value;
|
||||
}
|
||||
$authmethod->connect ();
|
||||
try
|
||||
{
|
||||
$authmethod->authentication ($email, $password);
|
||||
$_SESSION["domframework"]["authentication"]["authcache"] =
|
||||
$authmethod->getdetails ();
|
||||
$_SESSION["domframework"]["authentication"]["lastcheck"] = time ();
|
||||
return $authmethod->getdetails ();
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
trigger_error ("Authentication error for '$email' : ".
|
||||
"$classname : ".$e->getMessage(), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
trigger_error ("Bad login/password for '$email'", E_USER_WARNING);
|
||||
return _("Bad login/password");
|
||||
}
|
||||
|
||||
/** Add the authentication routes to the routing model */
|
||||
public function routes ()
|
||||
{
|
||||
$authObj = $this;
|
||||
$this->route->get ("authentication/logout", function () use ($authObj)
|
||||
{
|
||||
$authObj->logout ();
|
||||
});
|
||||
|
||||
$this->route->get ("authentication/{url}", function ($url) use ($authObj)
|
||||
{
|
||||
$authObj->pageHTML ($url);
|
||||
});
|
||||
|
||||
$this->route->post ("authentication/{url}", function ($url) use ($authObj)
|
||||
{
|
||||
$authObj->verifAuthLoginPage ($url);
|
||||
});
|
||||
|
||||
$this->route->get ("authentication", function () use ($authObj)
|
||||
{
|
||||
$authObj->pageHTML ();
|
||||
});
|
||||
|
||||
$this->route->post ("authentication", function () use ($authObj)
|
||||
{
|
||||
$authObj->verifAuthLoginPage ();
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user