2016-10-23 1 views
2

Je construis une boutique en ligne basée sur le framework slim3. J'ai besoin de gérer une requête POST de serveur à serveur pour confirmer si le paiement a réussi. J'ai ajouté CSRF au récipient comme celui-ci:Slim3 exclut la route du middleware CSRF

$container['csrf'] = function($container) { 
    return new \Slim\Csrf\Guard; 
}; 

et ajouté à l'application comme ceci:

$app->add($container->csrf); 

Et il fonctionne bien. Mais maintenant je dois être en mesure d'ajouter une exception à un certain itinéraire afin que j'obtienne les reques de courrier qu'ils envoient. Je n'ai pas trouvé de solution de travail jusqu'à présent.

Un conseil?

Répondre

2

Si vous avez besoin d'exclure une route d'un middleware, il y a deux options:

Option 1: Regroupez vos itinéraires.

Vous pouvez regrouper tous itinéraires sauf celui:

<?php 
$app->group('', function() { 

    // All routes declarations.... 

})->add($container->csrf); // Add middleware to all routes within the group 

// Declare your "exceptional" route outside the group 
$app->post('my-special-route-that-has-no-csrf-middleware', 'routeProcessor'); 

Option 2: utilisez votre propre middleware

Au lieu d'utiliser directement \Slim\Csrf\Guard, utilisez votre propre middleware qui la prolonge . Votre middleware vérifiera l'itinéraire, et si l'itinéraire est "exceptionnel", il passera.

Ajouter ce aux paramètres car vous avez besoin d'accéder à la route au sein de middleware:

$container['settings'] => [ 
    'determineRouteBeforeAppMiddleware' => true 
]; 

Créer le middleware extension orginales \Slim\Csrf\Guard:

<?php 
class MyCsrfMiddleware extends Slim\Csrf\Guard 
{ 
    // This method is processing every request in your application 
    public function processRequest($request, $response, $next) { 
     // Check if it's your "exceptional" route 
     $route = $request->getAttribute('route'); 
     if ($route == 'my-special-path') { 
      // If it is - just pass request-response to the next callable in chain 
      return $next($request, $response); 
     } else { 
      // else apply __invoke method that you've inherited from \Slim\Csrf\Guard 
      return $this($request, $response, $next); 
     } 
    } 
} 

///////////// 

$container['csrf'] = function($container) { 
    return new MyCsrfMiddleware; // Now the container returns your middleware under 'csrf' key 
}; 

Maintenant, il suffit d'ajouter le middleware à \Slim\App exemple:

$app->add('csrf:processRequest'); 
1

Pas si quelqu'un tire encore les cheveux à ce sujet (surtout si vous voulez utiliser des crochets).

J'ai trouvé une solution plus simple à l'aide de la réponse de Georgy.

Assurez la modification suivante au fichier réel Slim \ CSRF \ Guard 'Guard.php' et sa méthode __invoke. Ou tout simplement copier et coller le code ci-dessous ...

public function __invoke(ServerRequestInterface $request, ResponseInterface $response, callable $next) 
{ 

    $route = $request->getAttribute('routeInfo'); 

    $routeRequestInfo = $route['request']; 

    $requestUrl = $routeRequestInfo[1]; 


    if ($requestUrl == 'http://yoursite/the-url-you-want-to-exempt') 
    { 
     //This will just return the request to your application with applying the csrf. 
     return $next($request, $response); 

    } 
    else 
    { 

    $this->validateStorage(); 

    // Validate POST, PUT, DELETE, PATCH requests 
    if (in_array($request->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) { 
     $body = $request->getParsedBody(); 
     $body = $body ? (array)$body : []; 
     $name = isset($body[$this->prefix . '_name']) ? $body[$this->prefix . '_name'] : false; 
     $value = isset($body[$this->prefix . '_value']) ? $body[$this->prefix . '_value'] : false; 
     if (!$name || !$value || !$this->validateToken($name, $value)) { 
      // Need to regenerate a new token, as the validateToken removed the current one. 
      $request = $this->generateNewToken($request); 

      $failureCallable = $this->getFailureCallable(); 
      return $failureCallable($request, $response, $next); 
     } 
    } 

    // Generate new CSRF token if persistentTokenMode is false, or if a valid keyPair has not yet been stored 
    if (!$this->persistentTokenMode || !$this->loadLastKeyPair()) { 
     $request = $this->generateNewToken($request); 
    } 

    // Enforce the storage limit 
    $this->enforceStorageLimit(); 

    } 

    return $next($request, $response); 
} 
0
$container['csrf'] = function($container) { 
    $guard = new \Slim\Csrf\Guard; 
    $guard->setFailureCallable(function($request, $response, $next) use ($container) { 
     $request = $request->withAttribute("csrf_status", false); 
     if($request->getAttribute('csrf_status') === false) { 
      if($request->getAttribute('route')->getName()=== 'your-route-name'){ 
      return $next($request, $response); 
      } 
      return $response->withStatus(400)->withRedirect($container['router']->pathFor('home')); 
     } else { 
      return $next($request, $response); 
     } 
    }); 

    return $guard; 
};