Кто может плиз мне объяснить зачем нужен callback ? Для каких обстоятельств и зачем это нужно ? PHP: <?php use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; $app = new \Slim\App; $app->add(function (ServerRequestInterface $request, ResponseInterface $response, callable $next) { // Use the PSR 7 $request object return $next($request, $response); }); // Define app routes... $app->run();
callable для того, чтобы можно было несколько правил навесить. А это нужно для гибкости и избегания повтора. Допустим, к одному роуту может обратится только неавторизованный пользователь, к другому - любой авторизованный, к третьему - авторизованный, и набравший 30 баллов в крестики-нолики Вот авторизацию выносишь в отдельный middleware, и не повторяешь её два раза, а на третий роут навешиваешь ещё проверку баллов пользователя
это ж miidleware ) Тебе передается объект с запросом к серверу и ты на основе него можешь произвести некоторые действия с ответом. К примеру, проверить что все post-запросы должны быть сопровождены определенным токеном, или на все роуты начинающиеся с '/admin/' могут получить доступ лишь пользователи с определенными правами. Когда придет запрос все это выполнится в порядке добавления.
@mkramer суть понял не понял теперь как это в коде работает... Ужасные примеры в документации... Либо у меня ужасная не хватка знаний. Либо полное отсутствие понимания происходящего. --- Добавлено --- @romach @mkramer я думал для авторизации используются что - то типа этого PHP: $app->group('/users/{id:[0-9]+}', function () { $this->map(['GET', 'DELETE', 'PATCH', 'PUT'], '', function ($request, $response, $args) { // Find, delete, patch or replace user identified by $args['id'] })->setName('user'); $this->get('/reset-password', function ($request, $response, $args) { // Route for /users/{id:[0-9]+}/reset-password // Reset the password for user identified by $args['id'] })->setName('user-password-reset'); }); Но я пока не понял как это работает сижу разбираюсь --- Добавлено --- @romach @mkramer вы не вкурсе какого нибудь живого рабочего примера на slim на гитхабе чтобы можно было посмотреть и потыкать...
Группы используются, чтоб не повторять одно и тоже в каждом запросе. А middleware используется, чтоб навесить какие-то действия перед тем, как начнёт выполняться собственно роут, или сразу после того. На, посмотри, это я ради прикола как-то задачу Суриката на slim 3.0 решил (к тому же, хотелось попробовать третью версию, на реальных проектах только вторую использовал). У меня там используются и middleware в том числе, хотя можно было и больше их повесить https://github.com/mike-kramer/example --- Добавлено --- Я туда правда дамп базы не вывешивал, но там элементарная таблица. Код (Text): CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `login` varchar(100) NOT NULL, `password` varchar(100) NOT NULL, `birthday` date NOT NULL, `counter` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDBDEFAULT CHARSET=utf8
@romach @mkramer ну разобрался) PHP: $app = new \Slim\App(); $app->get('/', function ($request, $response) { return $response->getBody()->write('Hello World'); }); $app->group('/utils', function () use ($app) { $this->get('/date', function ($request, $response) { return $response->getBody()->write(date('Y-m-d H:i:s')); }); $this->get('/time', function ($request, $response) { return $response->getBody()->write(time()); }); })->add(function ($request, $response, $next) { $response->getBody()->write('It is now '); $response = $next($request, $response); $response->getBody()->write('. Enjoy!'); return $response; }); $app->run();
@romach @mkramer Подскажите плиз как реализовать такую конструкцию... По данной логике слим ругается. PHP: $app->get('/', Controller\Auth\AuthController::class . ':register'); $app->group('/admin', function () use ($app) { })->add(function (Request $request, Response $response, $admin) use ($app) { $app->get('/', Controller\Auth\AuthController::class . ':login'); // Нужно вызвать данный контроллер до проверки сессии.... При чём нужна ссылаться на /admin //но если вынести внешне ссылку, то да на неё заходит, то тогда не работает данная группа /admin :( if(!isset($_SESSION['user_id'])) { return $response->withStatus(302)->withHeader('Location', '/'); } $response = $admin($request, $response); return $response; }); Прошу обратить внимание. На этот вызов контроллера. Его нужно вызвать до проверки сессии. PHP: $app->get('/', Controller\Auth\AuthController::class . ':login'); Нужно вызвать данный контроллер до проверки сессии.... При чём нужна ссылаться на /admin Но если вынести внешне ссылку, то да на неё заходит и тогда не работает данная группа /admin --- Добавлено --- По какой логике заставить слим сделать то что я хочу?
Не совсем въезжаю, что ты пытаешься сделать, опиши без кода, но, ИМХО, тебе нужен не контроллер, а middleware свой написать --- Добавлено --- Ты не врубаешься. Эта строка не вызывает контроллер, она говорит, что при моршруте / надо вызывать метод логин экземпляра указанного класса. Посмотрел внимательно, тебе 100% надо организовать цепочку middleware. Они вызываются в том порядке, в котором добавлены.
Разобрался PHP: $app->get('/', Controller\Auth\AuthController::class . ':register'); $app->get('/admin[/]', Controller\Auth\AuthController::class . ':login'); $app->group('/admin', function () use ($app) { // а здесь уже будут ваше заблокированные маршруты от внешних глаз) Если вы не индентифицированы по сессии) })->add(function (Request $request, Response $response, $admin) { if(!isset($_SESSION['user_id'])) { return $response->withStatus(302)->withHeader('Location', '/'); } $response = $admin($request, $response); return $response; }); --- Добавлено --- @mkramer Что значит написать свой middleware а это что тогда ? PHP: $app->group('/admin', function () use ($app) { })->add(function (Request $request, Response $response, $admin) { if(!isset($_SESSION['user_id'])) { return $response->withStatus(302)->withHeader('Location', '/'); } $response = $admin($request, $response); return $response; }); который является контроллером у меня . вот прошу: PHP: <?php /** * Created by PhpStorm. * User: Леонид * Date: 04.04.2017 * Time: 17:35 */ namespace Admin\Controller\Auth; use Psr\Container\ContainerInterface; class AuthController { // constructor receives container instance public function __construct(ContainerInterface $container) { $this->container = $container; } public function login ($request, $response, $args) { $view = $this->container->get('view'); $view->render($response, 'admin/auth/login.html', []); return $response; } public function register($request, $response, $args) { $view = $this->container->get('view'); $view->render($response, 'admin/auth/register.html', []); return $response; } } --- Добавлено --- Если я делаю неправильно можешь пожалуйста рассказать что не так... ?
@mkramer @romach Выкладываю свой контроллер и индекс, не могу понять что не так с csrf делаю... Не работает. Сначала индекс: PHP: <?php require 'vendor/autoload.php'; /* $config = new config\Config();*/ $app = new \Slim\App([ 'settings' => [ 'displayErrorDetails' => true, ] ]); // Указываем необходимые параметры в контейнере $container = $app->getContainer(); $container['view'] = function ($container) { return new \Slim\Views\PhpRenderer(__DIR__ . '/Template'); }; // Занесём csrf в контейнер $container['csrf'] = function ($c) { return new \Slim\Csrf\Guard; }; // Вставим файл с маршрутами require_once __DIR__ . '/Admin/Router.php'; // session_start(); $app->run(); Теперь контроллер: PHP: <?php /** * Created by PhpStorm. * User: Леонид * Date: 04.04.2017 * Time: 17:35 */ namespace Admin\Controller\Auth; use \Psr\Http\Message\ServerRequestInterface as Request; use \Psr\Http\Message\ResponseInterface as Response; use Psr\Container\ContainerInterface; class AuthController { // constructor receives container instance public function __construct(ContainerInterface $container) { $this->container = $container; } public function login (Request $request, Response $response, $args) { $view = $this->container->get('view'); $csrf = $this->container->get('csrf'); $nameKey = $csrf->getTokenNameKey(); $valueKey = $csrf->getTokenValueKey(); $name = $request->getAttribute($nameKey); $value = $request->getAttribute($valueKey); $view->render($response, 'admin/auth/login.html',[ 'csrf' => [ 'keys' => [ 'name' => $nameKey, 'value' => $valueKey ], 'name' => $name, 'value' => $value ] ] ); return $response; } public function register(Request $request, Response $response, $args) { $view = $this->container->get('view'); $csrf = $this->container->get('csrf'); $nameKey = $csrf->getTokenNameKey(); $valueKey = $csrf->getTokenValueKey(); $name = $request->getAttribute($nameKey); // Эти значение почему то пусты :( $value = $request->getAttribute($valueKey); // Эти значение почему то пусты :( $view->render($response, 'admin/auth/register.html', [ 'csrf' => [ 'keys' => [ 'name' => $nameKey, 'value' => $valueKey ], 'name' => $name, 'value' => $value ] ]); return $response; } } --- Добавлено --- Кто нибудь помогите разобраться как правильно цифровую подпись реализовать то...
PHP: session_start(); $app = new \Slim\App(); // Register with container $container = $app->getContainer(); $container['csrf'] = function ($c) { return new \Slim\Csrf\Guard; }; $app->get('/',function (Request $request,Response $response, $args) { $nameKey = $this->csrf->getTokenNameKey(); $valueKey = $this->csrf->getTokenValueKey(); $name = $request->getAttribute($nameKey); $value = $request->getAttribute($valueKey); $tokenArray = [ $nameKey => $name, $valueKey => $value ]; print_r($tokenArray); return $response; })->add($container->get('csrf')); $app->run(); По такой схеме всё чудесно работает.... А вот по моей через контроллеры какая то фигня :///
PHP: <?php /** * Created by PhpStorm. * User: Леонид * Date: 04.04.2017 * Time: 17:35 */ namespace Admin\Controller\Auth; use \Psr\Http\Message\ServerRequestInterface as Request; use \Psr\Http\Message\ResponseInterface as Response; use Psr\Container\ContainerInterface; class AuthController { // constructor receives container instance public function __construct(ContainerInterface $container) { $this->csrf = new \Slim\Csrf\Guard(); $this->container = $container; } public function login (Request $request, Response $response, $args) { $view = $this->container->get('view'); $nameKey = $this->csrf->getTokenNameKey(); $valueKey = $this->csrf->getTokenValueKey(); $token = $this->csrf->generateToken(); $view->render($response, 'admin/auth/login.html',[ 'csrf' => [ 'keys' => [ 'name' => $nameKey, 'value' => $valueKey ], 'name' => $token[$nameKey], 'value' => $token[$valueKey] ] ] ); return $response; } public function register(Request $request, Response $response, $args) { $view = $this->container->get('view'); $nameKey = $this->csrf->getTokenNameKey(); $valueKey = $this->csrf->getTokenValueKey(); $token = $this->csrf->generateToken(); $view->render($response, 'admin/auth/register.html', [ 'csrf' => [ 'keys' => [ 'name' => $nameKey, 'value' => $valueKey ], 'name' => $token[$nameKey], 'value' => $token[$valueKey] ] ]); return $response; } } Сделал в контроллере не посредственный вызов guard... Токены генерируются... Теперь надо проверить их...
Проверкой csrf занимается middleware. Даже если у тебя контроллеры, тебе их надо добавить в ручную к путям, насколько я понял из документации. --- Добавлено --- Или добавь его к приложению, чтоб все post-запросы через него проходили. В конце концов, зайди в код расширения, посмотри, как работает. --- Добавлено --- Вообще, читай доку, там же всё есть: https://github.com/slimphp/Slim-Csrf ссылку взял с официального сайта slimframework. Я на все твои вопросы в доке за 2-3 минуты нахожу ответ
@mkramer ну токены генерировать я научился... А вот вопрос в том как их потом проверить нашёл метод валидейт, но я не совсем понимаю с чем он их сверяет, потому что я предполагал: что он хранит генерируемые значения в сессиях, но я не угадал.... --- Добавлено --- @mkramer я плохо перевариваю доку, не всё понимаю что написано... Английский у меня страдает.
Когда крепишь middleware к приложению или роуту - всё проверяется само, без твоего участия (о чём опять же написано в документации). Если хочешь сам проверять - никуда не крепишь, и делаешь, как на гитхабе нарисовано . Английский для понимания доки не суперский нужен. Разговариваю я по-английски через "ээээмм, мммммм...,", но доку читаю свободно. Просто приучай себя. В принципе, в доке-то большей частью исключительно специальная лексика, это не Шекспира читать в оригинале --- Добавлено --- https://github.com/slimphp/Slim-Csrf#manual-usage - полностью ручной режим, тогда ничего никуда не крепишь
@mkramer у меня без контроллеров всё поулчилось. Как в доке указано, а когда я вызываю в контроллерах csrf он почему то не генерирует токены... Я в ручную и сделал, посмотри в последнем примере. --- Добавлено --- @mkramer попробовал как с помощью add для middleware так и с помощью container, нет результатов в контроллерах. Там есть какой то способ ещё для использования твига, но чё то я его не до конца понял как использовать. Ну и ладно ща если получится в ручную то отпишу как сделал.
У меня работает. http://e.bug.kmk.4nmv.ru/csrf/ https://github.com/mike-kramer/example/blob/master/classes/Controller/Test.php https://github.com/mike-kramer/example/blob/master/index.php#L165 Может ты забываешь нужный middleware к обоим роутам добавить?
@mkramer а ты получается вызываешь csrf и в middleware и для каждого контроллера ещё раз... Оо --- Добавлено --- @mkramer я не догадался так попробовать.... --- Добавлено --- @mkramer вопрос такой а как middleware не по uri разделять ? Как просто сделать группу маршрутов не зависящих от uri
Маршруты - это и есть uri --- Добавлено --- А, дошло, что ты имел в виду. Не знаю, честно говоря. --- Добавлено --- Почему? Я просто к обоим маршрутам - и post и get добавляю middleware. в случае с get он генерирует мне значения, которые я потом использую, а в случае с post - ещё и проверяет
В самом slim такого пока нету - можешь предложить или реализовать Выкрутиться можно так, по идее: PHP: $routes = [ $app->get("route1", function (/*...*/) {}), $app->get("route2", function (/* ...*/) {}) ]; array_walk($routes, function ($r) { $r->add(new MyCustomMiddleware()});
@askanim возьми люмен: 1. Большинство твоих хотелок там уже реализовано нативно и из коробки 2. Есть русская дока 3. При необходимости легко мигрировать на laravel 4. По скорости он ни чем не уступает другим микро-фреймворкам
@romach тут чуть чуть поздняк метаться я уже половину slim расковырял Как то обидно бросать на пол пути --- Добавлено --- @mkramer Оригинально --- Добавлено --- Давайте построим сообщество по micro framework slim 1. сделаем для него сайт и русифицируем доку. 2. Внедрим дополнения (новый функционал). 3. Сделаем чат на gitter.