Demo entry 3348352

Image model in pixis

   

Submitted by anonymous on Dec 17, 2015 at 11:03
Language: PHP. Code size: 9.1 kB.

<?php

class User {

    /**
     * @var int $cookieExpire Время жизни куки в секундах.
     */
    private static $cookieExpire = 3600 * 24 * 7;

    /**
     * @var string $cookiePath Видимость куки на сайте.
     */
    private static $cookiePath = '/';

    /**
     * @var string $cookieDomain Домен, которому доступны куки.
     */
    private static $cookieDomain = '';

    /**
     * @var bool $cookieSecure Передача куки по защищённому HTTPS-соединению.
     */
    private static $cookieSecure = false;

    /**
     * @var bool $cookieHttponly Доступность куки только через HTTP-протокол.
     */
    private static $cookieHttponly = true;

    /**
     * Установливает куку
     *
     * @param string $name
     * @param string $value
     * @return bool
     */
    public static function setCookie($name, $value) {
        return setcookie(
            $name,
            $value,
            time() + self::$cookieExpire,
            self::$cookiePath,
            self::$cookieDomain,
            self::$cookieSecure,
            self::$cookieHttponly
        );
    }

    /**
     * Удаляет куку
     *
     * @param string $name
     * @return bool
     */
	public static function unsetCookie($name) {
		return setcookie($name,
			null,
			time() - 3600,
			self::$cookiePath,
			self::$cookieDomain,
			self::$cookieSecure,
			self::$cookieHttponly
        );
	}

    /**
     * Проверяет IP-адрес на соответствие IPv4-формату
     *
     * @param string $IPv4
     * @return bool
     */
    private static function isIPv4 ($IPv4) {
        return (bool) filter_var($IPv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
    }

    /**
     * Обрезает IPv4-адрес до определённой точки
     *
     * @param string $IPv4
     * @param int $length Номер точки, до которой нужно обрезать IPv4.
     * @return string|false Вернёт укороченный IP-адрес (127.0) или false в случае работы не с IPv4.
     */
    private static function trimIPv4 ($IPv4, $length = 2) {
        if (self::isIPv4($IPv4)) {
            return implode('.', array_slice(explode('.', $IPv4), 0, $length));
        }
        return false;
    }

    /**
     * Генерирует хеш-строку по алгоритму SHA-512
     *
     * @return string
     */
    private static function getSha512 () {
        return hash('sha512', uniqid(rand(0, 9), true));
    }

	/**
	 * Проверяет пользователя по логину и паролю
	 *
	 * @param string $login
	 * @param string $password
	 * @throws UserException
	 * @return int Вернёт идентификатор пользователя.
	 */
	public static function verifyMember ($login, $password) {

		$data = Db::get('User', ['id', 'password'], ['login' => $login]);

		if (!$data)
			throw new UserException("Пользователя с логином @{$login} не существует.");

		if (!password_verify($password, $data['password']))
			throw new UserException('Вы указали неверный пароль.');

		return (int) $data['id'];

	}

	/**
	 * Добавляет нового пользователя
	 *
	 * @param string $login
	 * @param string $password
	 * @throws UserException
	 * @return array Вернёт данные о новом пользователе в виде массива.
	 */
	public static function addMember ($login, $password) {

		if (Db::has('User', ['login' => $login]))
			throw new UserException("Пользователь с логином @{$login} уже существует.");

		Db::insert('User', [
			'login' => $login,
			'password' => password_hash($password, PASSWORD_BCRYPT)
		]);

		$id = Db::get('User', 'id', ['login' => $login]);

		return [
			'id' => (int) $id,
			'login' => $login,
			'password' => $password
		];

	}

	/**
	 * Устанавливает данные авторизации
	 *
	 * @param int $uid Айди пользователя.
	 * @param bool $remember Запомнить пользователя через куки.
	 * @throws UserException В случае повторной авторизации.
     * @throws UserException В случае работы не с IPv4.
	 * @return true
	 */
	public static function setAuth ($uid, $remember = false) {

		$serverAgent = $_SERVER['HTTP_USER_AGENT'];
		$serverAddr = $_SERVER['REMOTE_ADDR'];

		if (self::isAuth())
			throw new UserException('Вы уже авторизованы.');

        if (!self::isIPv4($serverAddr))
            throw new UserException('Включите IPv4.');

		if ($remember) {

			$token = self::getSha512();
			$series = self::getSha512();

			if (self::setCookie('Auth', $token . '_' . $series)) {

				$db = Db::insert('Auth', [
                    'uid' => $uid,
                    'token' => $token,
                    'series' => $series,
                    'agent' => $serverAgent,
                    'addr' => ip2long($serverAddr)
                ]);

				if ($db == 0)
                    self::unsetCookie('Auth');

			}

		}

		$_SESSION['Auth'] = [
			'uid' => (int) $uid,
			'agent' => md5($serverAgent), // используем md5() для сокращения длины строки
			'addr' => self::trimIPv4($serverAddr, 2) // обрезаем IP-адрес до второй точки
		];

		return true;

	}

	/**
	 * Определяет авторизован ли пользователь по сессии и если нет, тогда
     * пытается авторизовать его с помощью куки, если она была установлена
     *
	 * @return bool
	 */
	public static function isAuth () {

		// Проверяем данные сессии
		if (isset($_SESSION['Auth'])) {

            /*
             * Проверяем наличие ключей в массиве $_SESSION['Auth'], которые
             * были выданы при авторизации пользователя методом setAuth(). Если
             * не будет найден хотя бы один ключ, тогда удаляем $_SESSION['Auth'] и
             * возвращаем false.
             */
			foreach (['uid', 'agent', 'addr'] as $key) {
				if (!isset($_SESSION['Auth'][$key])) {
					unset($_SESSION['Auth']);
					return false;
				}
			}

            // конвертируем ключи $_SESSION['Auth'] в $uid, $agent, $addr
			extract($_SESSION['Auth']);

            // проверяем, является ли айди пользователя числовым значением
			if (!preg_match('#^\d+$#', $uid)) {
				unset($_SESSION['Auth']);
				return false;
			}

			$serverAgent = $_SERVER['HTTP_USER_AGENT'];
			$serverAddr = $_SERVER['REMOTE_ADDR'];

            /*
             * Проверяем на соответствие информацию о типе и версии браузера и
             * операционной системы посетителя $_SERVER['HTTP_USER_AGENT'], а также
             * IPv4-адрес пользователя $_SERVER['REMOTE_ADDR'] со значениями в сессии,
             * которые были добавлены методом setAuth(). $_SERVER['HTTP_USER_AGENT'] оборачивается
             * в md5() для уменьшения длины строки, а $_SERVER['REMOTE_ADDR'] обрезается до второй
             * точки из-за частой смены IP. Если участок кода не проходит проверку,
             * тогда считаем пользователя не авторизованным и удаляем $_SESSION['Auth'].
             */
			if ($agent != md5($serverAgent) || $addr != self::trimIPv4($serverAddr, 2)) {
				unset($_SESSION['Auth']);
				return false;
			}

			return true;

		// Авторизуем пользователя по кукам
		} elseif (isset($_COOKIE['Auth'])) {

			if (!preg_match('#^\w+\_\w+$#', $_COOKIE['Auth']))
				return false;

			list($token, $series) = explode('_', $_COOKIE['Auth']);

			$auth = Db::get('Auth', ['uid', 'token', 'series', 'agent', 'addr'], ['series' => $series]);

			if (!$auth || $auth['token'] != $token) {
				self::clearAuth();
				return false;
			}

			$addr = long2ip($auth['addr']);

			$serverAgent = $_SERVER['HTTP_USER_AGENT'];
			$serverAddr = $_SERVER['REMOTE_ADDR'];

			if ($auth['agent'] != $serverAgent || self::trimIPv4($addr) != self::trimIPv4($serverAddr)) {
				self::clearAuth();
				return false;
			}

            $token = self::getSha512();

			if (self::setCookie('Auth', $token . '_' . $series)) {

				$db = Db::update('Auth', [
                    'token' => $token,
                    'addr' => ip2long($serverAddr),
                    '#lastdate' => 'NOW()'
                ], [
                    'series' => $series
                ]);

				if ($db == 0)
                    self::unsetCookie('Auth');

			}

			$_SESSION['Auth'] = [
				'uid' => (int) $auth['uid'],
				'agent' => md5($serverAgent),
				'addr' => self::trimIPv4($serverAddr)
			];

			return true;

		}

		return false;

	}

    /**
     * Удаляет данные авторизации
     *
     * @return void
     */
    public static function clearAuth () {
        if (isset($_COOKIE['Auth']) && preg_match('#^\w+\_\w+$#', $_COOKIE['Auth'])) {
            list($token, $series) = explode('_', $_COOKIE['Auth']);
            Db::delete('Auth', ['series' => $series]);
            self::unsetCookie('Auth');
        }
        if (isset($_SESSION['Auth']))
            unset($_SESSION['Auth']);
    }

    /**
     * Получает идентификатор авторизованного пользователя из сессии
     *
     * @return int Вернёт айди пользователя или ноль.
     */
    public static function getId () {
        if (self::isAuth()) {
            return (int) $_SESSION['Auth']['uid'];
        }
        return 0;
    }

}

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).