У меня есть клиент, который пишет API-интерфейс Apigility, который должен взаимодействовать с базой данных, которая уже существует. Сюда также входит таблица пользователей, которая должна использоваться с аутентификацией Apigility OAuth2.
Получить интеграцию OAuth 2 от Apigility для общения с конкретным именем таблицы довольно просто. Просто добавьте этот конфиг:
'storage_settings' => array(
'user_table' => 'user',
),
Соответствующему адаптеру в конфигурации zf-mvc-auth => аутентификации.
Однако, если вы хотите использовать разные имена столбцов, это немного сложнее, так как они жестко закодированы в классе OAuth2 \ Storage \ Pdo. Чтобы компоненты Apigility OAuth2 могли просматривать правильные столбцы, вы создаете свой собственный адаптер OAuth2. Я решил расширить ZF \ OAuth2 \ Adapter \ PdoAdapter, который расширяет OAuth2 \ Storage \ Pdo, и перейти оттуда.
ZF \ OAuth2 \ Adapter \ PdoAdapter расширяет базовый класс для добавления хэширования bcrypt. Это хорошо, так что это хорошее место для начала. Я создал новый модуль MyAuth для хранения моего адаптера и его фабрики. Адаптер выглядит так:
<?php
namespace MyAuth;
use ZF\OAuth2\Adapter\PdoAdapter;
/**
* Custom extension of PdoAdapter to validate against the WEB_User table.
*/
class OAuth2Adapter extends PdoAdapter
{
public function __construct($connection, $config = array())
{
$config = [
'user_table' => 'legacy_user'
];
return parent::__construct($connection, $config);
}
public function getUser($username)
{
$sql = sprintf(
'SELECT * from %s where email_address=:username',
$this->config['user_table']
);
$stmt = $this->db->prepare($sql);
$stmt->execute(array('username' => $username));
if (!$userInfo = $stmt->fetch(\PDO::FETCH_ASSOC)) {
return false;
}
// the default behavior is to use "username" as the user_id
return array_merge(array(
'user_id' => $username
), $userInfo);
}
public function setUser($username, $password,
$firstName = null, $lastName = null)
{
// do not store in plaintext, use bcrypt
$this->createBcryptHash($password);
// if it exists, update it.
if ($this->getUser($username)) {
$sql = sprintf(
'UPDATE %s SET pwd=:password, firstname=:firstName,
surname=:lastName WHERE username=:username',
$this->config['user_table']
);
$stmt = $this->db->prepare($sql);
} else {
$sql = sprintf(
'INSERT INTO %s (email_address, pwd, firstname, surname)
VALUES (:username, :password, :firstName, :lastName)',
$this->config['user_table']
);
$stmt = $this->db->prepare($sql);
}
return $stmt->execute(compact('username', 'password', 'firstName',
'lastName'));
}
protected function checkPassword($user, $password)
{
return $this->verifyHash($password, $user['pwd']);
}
}
Этот код для getUser и setUser () взят непосредственно из OAuth2 \ Storage \ Pdo, и все, что я сделал, это изменил имена столбцов. В этом случае у меня есть email_address для моего имени пользователя и pwd для столбца пароля. Аналогично, я написал свой собственный checkPassword на основе ZF \ OAuth2 \ Adapter \ PdoAdapter, снова изменив ключ массива для проверки на «pwd».
Теперь, когда у нас есть фактическая работа, нам нужно подключить ее к Apigility.
Во-первых, нам нужна фабрика, чтобы DIC мог создать экземпляр нашего адаптера:
<?php
namespace MyAuth;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\Adapter\Driver\Pdo\Pdo as PdoDriver;
class OAuth2AdapterFactory implements FactoryInterface
{
/**
* Create service
*
* @param ServiceLocatorInterface $serviceLocator
* @return OAuth2Adapter
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$connection = $serviceLocator->get('DB\Master');
if (!$connection->getDriver() instanceof PdoDriver) {
throw new \RuntimeException("Need a PDO connection!");
}
$pdo = $connection->getDriver()->getConnection()->getResource();
return new OAuth2Adapter($pdo);
}
}
Это довольно стандартный код. Обратите внимание, что DB \ Master — это имя соединения с базой данных, которое установлено в администраторе Apigility. Я немного ленив и полагаю, что это адаптер на основе PDO. Если это не так, он взорвется, поэтому, если вы не используете PDO, он не будет работать как есть!
Чтобы зарегистрировать новый адаптер аутентификации в Apigility, создайте файл конфигурации в config / autoload и вызовите его myauth.global.php или что-то в этом роде:
<?php
return [
'zf-mvc-auth' => [
'authentication' => [
'adapters' => [
'MyAuth' => [
'adapter' => 'ZF\\MvcAuth\\Authentication\\OAuth2Adapter',
'storage' => [
'storage' => 'MyAuth\OAuth2Adapter',
'route' => '/oauth',
],
],
],
],
],
];
Адаптер называется MyAuth и теперь доступен для выбора на страницах конфигурации API администратора:
Подводить итоги
В общем, действительно легко написать собственную аутентификацию OAuth 2 для Apigility, поскольку это очень гибкая платформа. Я просто изменил имена столбцов здесь, но было бы достаточно просто написать адаптер для другой системы хранения, хотя вам придется переопределить больше методов и, возможно, начать с более подходящего базового класса.