0

I created an app using Slim 2 a while ago and I'm trying to add Angular. It's been going well so far, but I can no longer use the CSRF protection that I was using since Angular is handling all my post requests. Below is the Before Middleware I had working.

<?php

namespace Cache\Middleware;

use Exception;
use Slim\Middleware;

class CsrfMiddleware extends Middleware {
protected $key;

public function call() {

    $this->key = $this->app->config->get('csrf.key');

    $this->app->hook('slim.before', [$this, 'check']);

    $this->next->call();
}

public function check() {
    if (!isset($_SESSION[$this->key])) {
        $_SESSION[$this->key] = $this->app->hash->hash($this->app->randomlib->generateString(128));
    }

    $token = $_SESSION[$this->key];

    if (in_array($this->app->request()->getMethod(), ['POST', 'PUT', 'DELETE'])) {
        $submittedToken = $this->app->request()->post($this->key) ?: '';

        if (!$this->app->hash->hashCheck($token, $submittedToken)) {
            throw new Exception('CSRF token mismatch');
        }
    }

    $this->app->view()->appendData([
        'csrf_key' => $this->key,
        'csrf_token' => $token
    ]);
}

}

I know that angular automatically looks for a token named XSRF-TOKEN and adds it to the header as X-XSRF-TOKEN. How can I modify the middleware below to write, read, and compare the correct values.

EDIT:

After looking at this again and checking the slim documentation, I changed the line:

$submittedToken = $this->app->request()->post($this->key) ?: '';

to this:

$submittedToken = $this->app->request->headers->get('X-XSRF-TOKEN') ?: '';

If I'm right, this assigns the $submittedToken the value passed as X-XSRF-TOKEN in the header. It's throwing the exception with the message from the middleware "CSRF token mismatch". This feels like progress. Below is the relevant Angular:

app.controller('itemsCtrl', ['$scope', '$http', function($scope, $http) {

    // Initailize object when the page first loads
    $scope.getAll = function() {
        $http.post('/domain.com/admin/getNames').success(function(data) {
            $scope.names = data;
        });
    }

EDIT

Below is where the php code stands now. I think this is working. I've received the expected CSRF error when I remove the cookie or alter the value of the $token before submitting a form. I'm a little concerned about what will happen when I have multiple users on. I haven't tested it yet. Based on this revision, does the protection appear sound?

<?php

namespace Cache\Middleware;

use Exception;
use Slim\Middleware;

class CsrfMiddleware extends Middleware {
protected $key;

public function call() {

    $this->key = $this->app->config->get('csrf.key');

    $this->app->hook('slim.before', [$this, 'check']);

    $this->next->call();
}

public function check() {
    // if (!isset($_SESSION[$this->key])) {
    if (!isset($_SESSION[$this->key])) {
        // $_SESSION[$this->key] = $this->app->hash->hash($this->app->randomlib->generateString(128));
        $this->app->setcookie($this->key, $this->app->hash->hash($this->app->randomlib->generateString(128)));
    }

    // $token = $_SESSION[$this->key];
    if(isset($_COOKIE[$this->key])) {
        $token = $_COOKIE[$this->key];
    }

    if (in_array($this->app->request()->getMethod(), ['POST', 'PUT', 'DELETE'])) {
        // $submittedToken = $this->app->request()->post($this->key) ?: '';
        $submittedToken = $this->app->request->headers->get('X-XSRF-TOKEN') ?: '';

        if (!$this->app->hash->hashCheck($token, $submittedToken)) {
            throw new Exception('CSRF token mismatch');
        }
    }
}
}
4

1 に答える 1

0

$http Cross Site Request Forgery (XSRF) Protectionの Angular ドキュメントから:

ヘッダーの名前は、構成時の $httpProvider.defaults、実行時の $http.defaults、または要求ごとの構成オブジェクトの xsrfHeaderName および xsrfCookieName プロパティを使用して指定できます。

したがって、別の Cookie 名/ヘッダー名を使用するように変更するには、それらの値を変更します。

于 2017-01-09T23:15:43.330 に答える