# 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);
}
}