pupadupa
pupadupa

Reputation: 1640

yii2 Unable to verify your data submission

I use nginx, PHP 5.5.14, php-fpm, yii2, mac os.

I changed yii config to store session in database (postgress, user is superuser). This is in my config:

  'session' => [
        'class' => 'yii\web\DbSession',
        'sessionTable' => 'session',
    ],

And now when I try to register new user I've got this error:

Bad Request (#400)
Unable to verify your data submission

Here is a part of log:

10  17:25:57.434    info    yii\db\Command::query   SELECT "data" FROM "session" WHERE "expire">1425993957 AND "id"='cfg9sutufqchr1tdose4cack15'
/Users/pupadupa/Dev/www/mint-office-web/components/Controller.php (41)
11  17:25:57.442    info    yii\web\Session::open   Session started
/Users/pupadupa/Dev/www/mint-office-web/components/Controller.php (41)
12  17:25:57.450    error   yii\web\HttpException:400   exception 'yii\web\BadRequestHttpException' with message 'Не удалось проверить переданные данные.' in /Users/pupadupa/Dev/www/mint-office-web/vendor/yiisoft/yii2/web/Controller.php:110
Stack trace:
#0 /Users/pupadupa/Dev/www/mint-office-web/components/Controller.php(41): yii\web\Controller->beforeAction(Object(app\controllers\user\RegistrationAction))
#1 /Users/pupadupa/Dev/www/mint-office-web/vendor/yiisoft/yii2/base/Controller.php(149): app\components\Controller->beforeAction(Object(app\controllers\user\RegistrationAction))
#2 /Users/pupadupa/Dev/www/mint-office-web/vendor/yiisoft/yii2/base/Module.php(455): yii\base\Controller->runAction('registration', Array)
#3 /Users/pupadupa/Dev/www/mint-office-web/vendor/yiisoft/yii2/web/Application.php(83): yii\base\Module->runAction('user/registrati...', Array)
#4 /Users/pupadupa/Dev/www/mint-office-web/vendor/yiisoft/yii2/base/Application.php(375): yii\web\Application->handleRequest(Object(yii\web\Request))
#5 /Users/pupadupa/Dev/www/mint-office-web/web/index.php(20): yii\base\Application->run()
#6 {main}
13  17:25:57.454    trace   yii\base\Controller::runAction  Route to run: index/error

BTW,

  1. I've got <?= Html::csrfMetaTags() ?> in head section and I have csrf input in my form. So it seems not the problem
  2. I don't want to do public $enableCsrfValidation = false; because I think it's not solution but workaround.

How could I understand what cause this error? As I mentioned earlier problem only appears when I store session in database.


Some additional information: I could set and get variable from session. For example, I put it in beoreAction of Controller.php

Yii::$app->session->set('test', 'qwe');
$t = Yii::$app->session->get('test') ;
var_dump($t);

But after that If I comment first line like this

//Yii::$app->session->set('test', 'qwe');
$t = Yii::$app->session->get('test') ;
var_dump($t);

and refresh the page - I recieve NULL (BTW I could see Cookie:PHPSESSID=cfg9sutufqchr1tdose4cack15 in cookies after refresh).

So it seems there are some problems with session (DbSession) or maybe my php/php-fpm/nginx settings.


My UserController.php:

<?php

namespace app\controllers;


use app\components\Controller;
use app\models\Client;
use app\models\User;
use yii\filters\AccessControl;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;

class UserController extends Controller
{

    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['logout', 'employee'],
                'rules' => [
                    [
                        'actions' => ['logout',],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                    [
                        'actions' => ['employee', 'employee_add'],
                        'allow' => true,
                        'roles' => [ROLE_CLIENT_ADMIN],
                    ],
                ],

            ],
        ];
    }

    public function actions()
    {
        return [
            'login' => 'app\controllers\user\LoginAction',
            'logout' => 'app\controllers\user\LogoutAction',
            'restore' => 'app\controllers\user\RestoreAction',
            'registration' => 'app\controllers\user\RegistrationAction',
            'employee' => 'app\controllers\user\EmployeeAction',
            'employee_add' => 'app\controllers\user\EmployeeAddAction',
            //'passwd' => 'app\controllers\user\PasswdAction',
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV === 'dev' ? 'testme' : null,
            ],
        ];
    }

    /**
     * @param int $clientId
     * @return Client
     * @throws BadRequestHttpException
     * @throws NotFoundHttpException
     */
    public function getClient($clientId)
    {
        if (!\Yii::$app->user->can(ROLE_ADMIN)) {
            /* @var User $user */
            $user = \Yii::$app->user->identity;
            $clientId = $user->client_id;
        }
        if (!$clientId) {
            throw new BadRequestHttpException('Bad request');
        }

        $client = Client::find()->where(['id' => $clientId])->one();
        if (!$client) {
            throw new NotFoundHttpException('Компания не найдена');
        }

        return $client;
    }

} 

My RegistrationAction.php:

<?php
namespace app\controllers\user;


use app\models\UserConfirm;
use Yii;
use app\components\Action;
use app\forms\RegistrationForm;
use yii\web\NotFoundHttpException;

class RegistrationAction extends Action
{

    public function run($key = null)
    {
        if ($key !== null) {
            /* @var UserConfirm $confirm */
            $confirm = UserConfirm::find()->andWhere('expire > NOW()')->andWhere([
                    'key' => $key,
                    'action' => 'reg'
                ])->one();
            if (!$confirm) {
                throw new NotFoundHttpException('Key not found');
            }

            $user = $confirm->user;
            $user->enabled = true;
            $user->last_login = date('Y-m-d H:i:s');
            $user->save();

            $confirm->delete();

            Yii::$app->user->login($user, 0);
            return $this->controller->goHome();
        }

        $model = new RegistrationForm();
        if ($model->load($_POST) && $model->validate() && $model->register()) {

            $subject = Yii::$app->name . ' - Success';
            $message = $this->controller->renderPartial(
                '//email/registration',
                [
                    'username' => $model->email,
                    'password' => $model->password,
                    'key' => $model->key,
                    'keyExpire' => $model->keyExpire
                ]
            );

            $res = Yii::$app->mailer->compose()
                ->setTo($model->email)
                ->setFrom([Yii::$app->params['from'] => Yii::$app->params['fromName']])
                ->setSubject($subject)
                ->setHtmlBody($message)
                ->send();

            Yii::$app->session->setFlash('registrationFormSubmitted');
            return $this->controller->refresh();
        }

        return $this->controller->render('registration', ['model' => $model]);
    }

}

Upvotes: 6

Views: 9159

Answers (5)

Jason
Jason

Reputation: 74

Not sure if it's late, but I found this solution which worked for me in a similar case of Yii2 framework spitting 400 Bad Request at POST form requests.

Simply add this code in your form to manually include a CSRF input field for the key and Yii2 will accept the data submission:

<?php

use Yii;
echo Html::tag('input', '', ['type' => 'hidden', 'name' => '_csrf-backend', 'value' => Yii::$app->request->getCsrfToken()]);

?>

Note: this is for the advanced template. In the long run I suggest not to use a framework that bases on short tags as PHPers would know its a curse.

Upvotes: -1

Vijay Padhariya
Vijay Padhariya

Reputation: 81

What I did is, I just make the "csrfParam" different for both backend and frontend and after "php init" command everything is now working fine.

Not sure whether its a bug or we must have to set different "csrfParam" in case if we use DBsession.

Upvotes: 0

Goke Obasa
Goke Obasa

Reputation: 4908

I think this happens atimes when the server is messed up, all I needed to do was to restart my apache server.

For apache on MacOSx

sudo apachectl restart

For apache on Linux

sudo service apache2 restart

or

sudo service httpd restart

Upvotes: 1

user2266928
user2266928

Reputation: 475

i hv used this while calling logout 
 $menuItems[] = [
                 'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
                 'url' => ['/site/logout'],
                 //  'linkOptions' => ['data-method' => 'get']
                 'data-method' => 'get'
             ];

in main .php change post to get 
---------------------------------------------------
and have changes this also
   $url = Html::a('Logout',
             ['/site/logout'],
             ['class' => 'btn btn-success', 'data-method' => 'get']);

this is also in main.php
--------------------------------------------------------------------
in behaviour of site controller also

 public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'only' => ['logout', 'signup','index'],
                'rules' => [
                    [
                        'actions' => ['signup'],
                        'allow' => true,
                        'roles' => ['?'],
                    ],
                    [
                        'actions' => ['logout','index'],

                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                   'logout' => ['get'],
                ],
            ],
        ];
    }


change post to get...and it will work....

Upvotes: 0

Jan Waś
Jan Waś

Reputation: 81

Looks like your session id changes. Check if the value of the session cookie changes after a second request. This happens when you misconfigure the domain that is set for the session cookie, make sure it matches the hostname in your URL.

Upvotes: 1

Related Questions