7

I have a custom module with a defined route as:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="custom_module" frontName="custom-module">
            <module name="Custom_Module" />
        </route>
    </router>
</config>

With previous versions of Magento both GET and POST requests would work fine to http://mywebsite.com/custom-module/controllername

After upgrading to Magento 2.3.0, GET requests still work as before, however POST requests now do not call the execute() method of the controller. Instead, they respond with a 200 OK and a response body that is the homepage html of the website.

Does this have to do with some Csrf security feature and form keys that was added in v2.3?

11

Please check more generous solution that does not change core functionality, you can use around plugin on Validate function of Magento\Framework\App\Request\CsrfValidator class

This implementation does not break the core functionality of Magento 2.1/2.2/2.3 versions.

di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\App\Request\CsrfValidator">
        <plugin name="csrf_validator_skip" type="Module\Vendor\Plugin\CsrfValidatorSkip" />
    </type>
</config>

CsrfValidatorSkip.php

<?php
namespace Module\Vendor\Plugin;
class CsrfValidatorSkip
{
    /**
     * @param \Magento\Framework\App\Request\CsrfValidator $subject
     * @param \Closure $proceed
     * @param \Magento\Framework\App\RequestInterface $request
     * @param \Magento\Framework\App\ActionInterface $action
     */
    public function aroundValidate(
        $subject,
        \Closure $proceed,
        $request,
        $action
    ) {
        if ($request->getModuleName() == 'Your_Module_frontName_Here') {
            return; // Skip CSRF check
        }
        $proceed($request, $action); // Proceed Magento 2 core functionalities
    }
}

Please star my Gist page at https://gist.github.com/ananth-iyer/59ecfabcbca73d6c2e3eeb986ed2f3c4 to encourage.

  • $request->getModuleName() always return blank – sumeet bajaj Jun 24 at 11:14
  • @AnanthMage2 Can you tell me where to add this? – Kowsigan Atsayam Sep 17 at 11:49
  • I am facing same issue. I added one or more custom modules. So, Can I need to add plugins in each and every module? If There are already exist di.xml files so what can I do? – sarvesh Dineshkumar Patel Nov 5 at 12:31
19

UPDATE: I changed the accepted answer to the one from @AnanthMage2 as it follows Magento's coding practices


Found the solution, your controller must implement CsrfAwareActionInterface and 2 of its methods:

use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\Request\InvalidRequestException;

class MyController extends \Magento\Framework\App\Action\Action implements CsrfAwareActionInterface
{
    public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException
    {
        return null;
    }

    public function validateForCsrf(RequestInterface $request): ?bool
    {
        return true;
    }
}

This solves the problem, but is also backwards incompatible, i.e. your module will now not work on Magento 2.2 and earlier. To make it backwards compatible, something like the following is needed:

use Magento\Framework\App\CsrfAwareActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\Request\InvalidRequestException;

if (interface_exists("Magento\Framework\App\CsrfAwareActionInterface"))
    include __DIR__ . "/MyController.m230.php";
else
    include __DIR__ . "/MyController.m220.php";

Where you would have the full and correct class declaration in each of the two files.

  • Working like a charm. this is what i am looking at.. thanks!! – Pravin Jan 12 at 15:44
  • Check this answer for backwards compatibility: magento.stackexchange.com/a/261410/74078 – gemig_hol Mar 17 at 17:26
  • 1
    The first part is great and compatible with 2.3. But the implementation of backward compatibility is out of the standards and Magento recommendations. – Ricardo Martins Aug 15 at 5:37
  • @RicardoMartins see the accepted answer for a standards based solution – snez Aug 15 at 13:01
  • where should I add this? – Kowsigan Atsayam Sep 17 at 9:40
1

Implement CsrfAwareActionInterface is a solution, but it makes the code not compatible with Magento < 2.3

Here is a trick (injecting the Key to the request on the Action) that is compatible with Magento 2.X

Put it in the constructor of the Action.

        // CsrfAwareAction Magento2.3 compatibility
        if (interface_exists("\Magento\Framework\App\CsrfAwareActionInterface")) {
            $request = $this->getRequest();
            if ($request instanceof HttpRequest && $request->isPost() && empty($request->getParam('form_key'))) {
                $formKey = $this->_objectManager->get(\Magento\Framework\Data\Form\FormKey::class);
                $request->setParam('form_key', $formKey->getFormKey());
            }
        }
  • $this->getRequest() is null in the __construct ... I guess it's only available in the execute() method. So, it will never enter this if. Didn't work for me at least. Magento 2.3.2. – Ricardo Martins Aug 15 at 5:31
0

One could provide a compatible solution to PHP 7.1< & Mage 2.3< if they were to outsource the validator to a different class, e.g.

if (PHP_VERSION_ID < 70100) {
    class Index extends Extendable\Main {}
} else {
    class Index extends Extendable\CsrCompatible {}
}

Where Extendable\Main has the logic for execute() {} and CsrCompatible can both extend Extendable\Main and implements CsrfAwareActionInterface. E.g:

class Main extends Action 
{
     execute() {...}
}

And

class CsrCompatible extends Main implements CsrfAwareActionInterface 
{
     //interface functions
}

The 5.6-7.0 will just never go into the CsrCompatible and therefore not throw an exception when it sees the fancy ?bool code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.