From: Marcel Werk Date: Fri, 12 Aug 2011 18:07:18 +0000 (+0200) Subject: Overhaul of the user authentication system X-Git-Tag: 2.0.0_Beta_1~1880 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=75afb100e53a118736cdec8a9c77d2dc947dd4b6;p=GitHub%2FWoltLab%2FWCF.git Overhaul of the user authentication system --- diff --git a/wcfsetup/install/files/lib/acp/form/LoginForm.class.php b/wcfsetup/install/files/lib/acp/form/LoginForm.class.php index 075968cfbf..94e0d0134c 100755 --- a/wcfsetup/install/files/lib/acp/form/LoginForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/LoginForm.class.php @@ -2,7 +2,8 @@ namespace wcf\acp\form; use wcf\data\user\User; use wcf\form\AbstractForm; -use wcf\system\auth\UserAuth; +use wcf\system\user\authentication\UserAuthenticationFactory; +use wcf\system\user\authentication\EmailUserAuthentication; use wcf\system\exception\PermissionDeniedException; use wcf\system\exception\UserInputException; use wcf\system\WCF; @@ -83,7 +84,26 @@ class LoginForm extends AbstractForm { * Validates the user access data. */ protected function validateUser() { - $this->user = UserAuth::getInstance()->loginManually($this->username, $this->password); + try { + $this->user = UserAuthenticationFactory::getUserAuthentication()->loginManually($this->username, $this->password); + } + catch (UserInputException $e) { + // TODO: create an option for the authentication with email address + if (true) { + if ($e->getField() == 'username') { + try { + $this->user = EmailUserAuthentication::getInstance()->loginManually($this->username, $this->password); + } + catch (UserInputException $e2) { + if ($e->getField() == 'username') throw $e; + throw $e2; + } + } + } + else { + throw $e; + } + } } /** diff --git a/wcfsetup/install/files/lib/system/auth/UserAuth.class.php b/wcfsetup/install/files/lib/system/auth/UserAuth.class.php deleted file mode 100644 index a4ad24f7b4..0000000000 --- a/wcfsetup/install/files/lib/system/auth/UserAuth.class.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @package com.woltlab.wcf - * @subpackage system.auth - * @category Community Framework - */ -abstract class UserAuth { - /** - * active instance - * @var wcf\system\auth\UserAuth - */ - protected static $instance = null; - - /** - * Returns an instance of the enabled user auth class. - * - * @return UserAuth - */ - public static function getInstance() { - if (self::$instance === null) { - // call loadInstance event - EventHandler::getInstance()->fireAction(__CLASS__, 'loadInstance'); - - // use default implementation - if (self::$instance === null) { - self::$instance = new UserAuthDefault(); - } - } - - return self::$instance; - } - - /** - * Prevents creating an additional instance. - */ - protected function __clone() {} - - /** - * Returns true, if this auth type supports persistent logins. - * - * @return boolean - */ - public abstract function supportsPersistentLogins(); - - /** - * Stores the user access data for a persistent login. - * - * @param User $user - * @param string $username - * @param string $password - */ - public abstract function storeAccessData(User $user, $username, $password); - - /** - * Does an manual user login. - * - * @param string $username - * @param string $password - * @param string $userClassname class name of user class - * @return User - */ - public abstract function loginManually($username, $password, $userClassname = 'wcf\data\user\User'); - - /** - * Does an automatic user login. - * - * @param boolean $persistent true = persistent login - * @param string $userClassname class name of user class - * @return User - */ - public abstract function loginAutomatically($persistent = false, $userClassname = 'wcf\data\user\User'); -} diff --git a/wcfsetup/install/files/lib/system/auth/UserAuthDefault.class.php b/wcfsetup/install/files/lib/system/auth/UserAuthDefault.class.php deleted file mode 100644 index 310938a926..0000000000 --- a/wcfsetup/install/files/lib/system/auth/UserAuthDefault.class.php +++ /dev/null @@ -1,99 +0,0 @@ - - * @package com.woltlab.wcf - * @subpackage system.auth - * @category Community Framework - */ -class UserAuthDefault extends UserAuth { - /** - * @see wcf\system\auth\UserAuth::supportsPersistentLogins() - */ - public function supportsPersistentLogins() { - return true; - } - - /** - * @see wcf\system\auth\UserAuth::loginManually() - */ - public function loginManually($username, $password, $userClassname = 'wcf\data\user\User') { - $user = User::getUserByUsername($username); - $userSession = new $userClassname(null, null, $user); - - if ($userSession->userID == 0) { - throw new UserInputException('username', 'notFound'); - } - - // check password - if (!$userSession->checkPassword($password)) { - throw new UserInputException('password', 'false'); - } - - return $userSession; - } - - /** - * @see wcf\system\auth\UserAuth::storeAccessData() - */ - public function storeAccessData(User $user, $username, $password) { - HeaderUtil::setCookie('userID', $user->userID, TIME_NOW + 365 * 24 * 3600); - HeaderUtil::setCookie('password', StringUtil::getSaltedHash($password, $user->salt), TIME_NOW + 365 * 24 * 3600); - } - - /** - * @see wcf\system\auth\UserAuth::loginAutomatically() - */ - public function loginAutomatically($persistent = false, $userClassname = 'wcf\data\user\User') { - if (!$persistent) return null; - - $user = null; - if (isset($_COOKIE[COOKIE_PREFIX.'userID']) && isset($_COOKIE[COOKIE_PREFIX.'password'])) { - if (!($user = $this->getUserAutomatically(intval($_COOKIE[COOKIE_PREFIX.'userID']), $_COOKIE[COOKIE_PREFIX.'password'], $userClassname))) { - $user = null; - // reset cookie - HeaderUtil::setCookie('userID', ''); - HeaderUtil::setCookie('password', ''); - } - } - - return $user; - } - - /** - * Returns a user object or null on failure. - * - * @param integer $userID - * @param string $password - * @param string $userClassname - * @return User - */ - protected function getUserAutomatically($userID, $password, $userClassname = 'wcf\data\user\User') { - $user = new $userClassname($userID); - if (!$user->userID || !$this->checkCookiePassword($user, $password)) { - $user = null; - } - - return $user; - } - - /** - * Validates the cookie password. - * - * @param User $user - * @param string $password - * @return boolean - */ - protected function checkCookiePassword($user, $password) { - return $user->checkCookiePassword($password); - } -} diff --git a/wcfsetup/install/files/lib/system/auth/UserAuthEmail.class.php b/wcfsetup/install/files/lib/system/auth/UserAuthEmail.class.php deleted file mode 100644 index 4abb2734d5..0000000000 --- a/wcfsetup/install/files/lib/system/auth/UserAuthEmail.class.php +++ /dev/null @@ -1,39 +0,0 @@ - - * @package com.woltlab.wcf - * @subpackage system.auth - * @category Community Framework - */ -class UserAuthEmail extends UserAuthDefault { - /** - * @see wcf\system\auth\UserAuth::loginManually() - * - * In this case $username is indeed not the username, but the e-mail address. - */ - public function loginManually($username, $password, $userClassname = 'wcf\data\user\User') { - $user = User::getUserByEmail($username); - $userSession = new $userClassname(null, null, $user); - - if ($userSession->userID == 0) { - throw new UserInputException('username', 'notFound'); - } - - // check password - if (!$userSession->checkPassword($password)) { - throw new UserInputException('password', 'false'); - } - - return $userSession; - } -} diff --git a/wcfsetup/install/files/lib/system/session/SessionHandler.class.php b/wcfsetup/install/files/lib/system/session/SessionHandler.class.php index e8416cd634..5c3d9d9387 100644 --- a/wcfsetup/install/files/lib/system/session/SessionHandler.class.php +++ b/wcfsetup/install/files/lib/system/session/SessionHandler.class.php @@ -2,9 +2,9 @@ namespace wcf\system\session; use wcf\data\user\group\UserGroup; use wcf\data\user\User; -use wcf\system\auth\UserAuth; use wcf\system\cache\CacheHandler; use wcf\system\exception\PermissionDeniedException; +use wcf\system\user\authentication\UserAuthenticationFactory; use wcf\system\user\storage\UserStorageHandler; use wcf\system\SingletonFactory; use wcf\system\WCF; @@ -354,7 +354,7 @@ class SessionHandler extends SingletonFactory { $sessionID = StringUtil::getRandomID(); // get user automatically - $this->user = UserAuth::getInstance()->loginAutomatically(); + $this->user = UserAuthenticationFactory::getUserAuthentication()->loginAutomatically(); // create user if ($this->user === null) { diff --git a/wcfsetup/install/files/lib/system/user/authentication/AbstractUserAuthentication.class.php b/wcfsetup/install/files/lib/system/user/authentication/AbstractUserAuthentication.class.php new file mode 100644 index 0000000000..d5df244dc7 --- /dev/null +++ b/wcfsetup/install/files/lib/system/user/authentication/AbstractUserAuthentication.class.php @@ -0,0 +1,15 @@ + + * @package com.woltlab.wcf + * @subpackage system.user.authentication + * @category Community Framework + */ +abstract class AbstractUserAuthentication extends SingletonFactory implements IUserAuthentication {} diff --git a/wcfsetup/install/files/lib/system/user/authentication/DefaultUserAuthentication.class.php b/wcfsetup/install/files/lib/system/user/authentication/DefaultUserAuthentication.class.php new file mode 100644 index 0000000000..a91118cf83 --- /dev/null +++ b/wcfsetup/install/files/lib/system/user/authentication/DefaultUserAuthentication.class.php @@ -0,0 +1,109 @@ + + * @package com.woltlab.wcf + * @subpackage system.user.authentication + * @category Community Framework + */ +class DefaultUserAuthentication extends AbstractUserAuthentication { + /** + * @see wcf\system\user\authentication\IUserAuthentication::supportsPersistentLogins() + */ + public function supportsPersistentLogins() { + return true; + } + + /** + * @see wcf\system\user\authentication\IUserAuthentication::storeAccessData() + */ + public function storeAccessData(User $user, $username, $password) { + HeaderUtil::setCookie('userID', $user->userID, TIME_NOW + 365 * 24 * 3600); + HeaderUtil::setCookie('password', StringUtil::getSaltedHash($password, $user->salt), TIME_NOW + 365 * 24 * 3600); + } + + /** + * @see wcf\system\user\authentication\IUserAuthentication::loginManually() + */ + public function loginManually($username, $password, $userClassname = 'wcf\data\user\User') { + $user = $this->getUserByLogin($username); + $userSession = (get_class($user) == $userClassname ? $user : new $userClassname(null, null, $user)); + + if ($userSession->userID == 0) { + throw new UserInputException('username', 'notFound'); + } + + // check password + if (!$userSession->checkPassword($password)) { + throw new UserInputException('password', 'false'); + } + + return $userSession; + } + + /** + * @see wcf\system\user\authentication\IUserAuthentication::loginAutomatically() + */ + public function loginAutomatically($persistent = false, $userClassname = 'wcf\data\user\User') { + if (!$persistent) return null; + + $user = null; + if (isset($_COOKIE[COOKIE_PREFIX.'userID']) && isset($_COOKIE[COOKIE_PREFIX.'password'])) { + if (!($user = $this->getUserAutomatically(intval($_COOKIE[COOKIE_PREFIX.'userID']), $_COOKIE[COOKIE_PREFIX.'password'], $userClassname))) { + $user = null; + // reset cookie + HeaderUtil::setCookie('userID', ''); + HeaderUtil::setCookie('password', ''); + } + } + + return $user; + } + + /** + * Returns a user object by given login name. + * + * @param string $login + * @return wcf\data\user\User + */ + protected function getUserByLogin($login) { + return User::getUserByUsername($login); + } + + /** + * Returns a user object or null on failure. + * + * @param integer $userID + * @param string $password + * @param string $userClassname + * @return wcf\data\user\User + */ + protected function getUserAutomatically($userID, $password, $userClassname = 'wcf\data\user\User') { + $user = new $userClassname($userID); + if (!$user->userID || !$this->checkCookiePassword($user, $password)) { + $user = null; + } + + return $user; + } + + /** + * Validates the cookie password. + * + * @param wcf\data\user\User $user + * @param string $password + * @return boolean + */ + protected function checkCookiePassword($user, $password) { + return $user->checkCookiePassword($password); + } +} diff --git a/wcfsetup/install/files/lib/system/user/authentication/EmailUserAuthentication.class.php b/wcfsetup/install/files/lib/system/user/authentication/EmailUserAuthentication.class.php new file mode 100644 index 0000000000..82e628c6ee --- /dev/null +++ b/wcfsetup/install/files/lib/system/user/authentication/EmailUserAuthentication.class.php @@ -0,0 +1,22 @@ + + * @package com.woltlab.wcf + * @subpackage system.user.authentication + * @category Community Framework + */ +class EmailUserAuthentication extends DefaultUserAuthentication { + /** + * @see wcf\system\user\authentication\DefaultUserAuthentication::getUserByLogin() + */ + protected function getUserByLogin($login) { + return User::getUserByEmail($login); + } +} diff --git a/wcfsetup/install/files/lib/system/user/authentication/IUserAuthentication.class.php b/wcfsetup/install/files/lib/system/user/authentication/IUserAuthentication.class.php new file mode 100644 index 0000000000..9ec3a0b51a --- /dev/null +++ b/wcfsetup/install/files/lib/system/user/authentication/IUserAuthentication.class.php @@ -0,0 +1,57 @@ + + * @package com.woltlab.wcf + * @subpackage system.user.authentication + * @category Community Framework + */ +interface IUserAuthentication { + /** + * Returns an unique instance of the authentication class + * + * @return wcf\system\user\authentication\IUserAuthentication + */ + public static function getInstance(); + + /** + * Returns true, if this authentication supports persistent logins. + * + * @return boolean + */ + public function supportsPersistentLogins(); + + /** + * Stores the user access data for a persistent login. + * + * @param wcf\data\user\User $user + * @param string $username + * @param string $password + */ + public function storeAccessData(User $user, $username, $password); + + /** + * Does a manual user login. + * + * @param string $username + * @param string $password + * @param string $userClassname class name of user class + * @return wcf\data\user\User + */ + public function loginManually($username, $password, $userClassname = 'wcf\data\user\User'); + + /** + * Does a user login automatically. + * + * @param boolean $persistent true = persistent login + * @param string $userClassname class name of user class + * @return wcf\data\user\User + */ + public function loginAutomatically($persistent = false, $userClassname = 'wcf\data\user\User'); +} diff --git a/wcfsetup/install/files/lib/system/user/authentication/UserAuthenticationFactory.class.php b/wcfsetup/install/files/lib/system/user/authentication/UserAuthenticationFactory.class.php new file mode 100644 index 0000000000..d8602f4493 --- /dev/null +++ b/wcfsetup/install/files/lib/system/user/authentication/UserAuthenticationFactory.class.php @@ -0,0 +1,45 @@ + + * @package com.woltlab.wcf + * @subpackage system.user.authentication + * @category Community Framework + */ +class UserAuthenticationFactory { + /** + * user authentication instance + * @var wcf\system\user\authentication\IUserAuthentication + */ + protected static $userAuthentication = null; + + /** + * Returns user authentication instance. + * + * @return wcf\system\user\authentication\IUserAuthentication + */ + public static function getUserAuthentication() { + if (static::$userAuthentication === null) { + // call loadInstance event + EventHandler::getInstance()->fireAction(__CLASS__, 'loadUserAuthentication'); + + // get default implementation + static::loadUserAuthentication(); + } + + return static::$userAuthentication; + } + + /** + * Loads the user authentication . + */ + protected static function loadUserAuthentication() { + static::$userAuthentication = DefaultUserAuthentication::getInstance(); + } +}