Просмотр поста

.
reaper
# Swank (26.04.2015 / 17:49)
reaper, Я о абстракных классах только слыхал и не в одном языке их не юзал и даже не помню когда код с абстракными классами видел, мне вообще неизвестно как их используют.
Для меня не так уж и легко
Ну вот например. Есть политика аутентификации, которая отвечает за создание и проверку токена.

interface PolicyInterface
{
    public function validateToken($token);
    public function createToken($credentials);
}


Допустим, что мы хотим иметь базовую реализацию методов createToken и validateToken, но хотим позволить юзеру самому решить, как проверять учётные данные.
Для этого сделаем абстрактный класс:

<?php
abstract class AbstractPolicy implements PolicyInterface
{
    const HASH_ALG = 'sha256';
    const DELIMITER = ':';
    private $secretKey;
    private $lifetime;

    public function __construct($secretKey, $lifetime)
    {
        $this->secretKey = $secretKey;
        $this->lifetime = $lifetime;
    }

    abstract protected function validateCredentials($credentials);

    public function validateToken($token)
    {
        $token = explode(self:ELIMITER, base64_decode($token));
        if (count($token) !== 3) {
            throw new AuthenticationException('The token is invalid.');
        }
        list($credentials, $expires, $hash) = $token;
        $credentials = base64_decode($credentials);
        if (!($this->validateCredentials($credentials) && $hash === $this->createTokenHash($credentials, $expires))) {
            throw new AuthenticationException('The token is invalid.');
        }
        if ($expires < time()) {
            throw new AuthenticationException('The token is expired.');
        }
    }

    public function createToken($credentials)
    {
        if (!is_string($credentials)) {
            throw new \InvalidArgumentException(sprintf('Expects string, %s given.', gettype($credentials)));
        }
        $expires = time() + $this->lifetime;
        $hash = $this->createTokenHash($credentials, $expires);

        return base64_encode(implode(':', [base64_encode($credentials), $expires, $hash]));
    }

    private function createTokenHash($credentials, $expires)
    {
        return hash_hmac(self::HASH_ALG, $credentials.$expires, $this->secretKey);
    }
}