yii2无法验证您的数据提交

时间:2015-03-10 13:43:33

标签: session yii csrf yii2

我使用的是nginx,PHP 5.5.14,php-fpm,yii2,mac os。

我将yii config更改为在数据库中存储会话(postgress,用户是超级用户)。 这是我的配置:

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

现在,当我尝试注册新用户时,我发现了这个错误:

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

以下是日志的一部分:

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

顺便说一句,

  1. 我在头部有<?= Html::csrfMetaTags() ?>,我的表格中有csrf输入。所以似乎不是问题
  2. 我不想做public $enableCsrfValidation = false;,因为我认为它不是解决方案而是解决方法。
  3. 我怎么能理解导致此错误的原因? 正如我之前提到的,只有在数据库中存储会话时才会出现问题。


    其他一些信息: 我可以设置并从会话中获取变量。例如,我将其放在beoreAction

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

    但之后如果我像这样评论第一行

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

    并刷新页面 - 我收到NULL(BTW我可以在刷新后看到Cookie:PHPSESSID=cfg9sutufqchr1tdose4cack15)。

    所以似乎会话(DbSession)或者我的php / php-fpm / nginx设置存在一些问题。


    我的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;
        }
    
    } 
    

    我的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]);
        }
    
    }
    

5 个答案:

答案 0 :(得分:1)

您的会话ID似乎发生了变化。检查会话cookie的值是否在第二次请求后发生更改。如果您错误配置了为会话cookie设置的域,请确保它与您的URL中的主机名匹配。

答案 1 :(得分:1)

我认为当服务器搞砸的时候会发生这种情况,我需要做的就是重新启动我的apache服务器。

对于MacOSx上的apache

sudo apachectl restart

对于Linux上的apache

sudo service apache2 restart

sudo service httpd restart

答案 2 :(得分:0)

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....

答案 3 :(得分:0)

我做的是,我只是让后端和前端的“csrfParam”不同,在“php init”命令之后,现在一切正常。

如果我们使用DBsession,不确定它是否是一个bug或我们必须设置不同的“csrfParam”。

答案 4 :(得分:-1)

不确定是否晚了,但是我发现此解决方案在类似Yii2框架的情况下对我有用,该框架在POST表单请求中吐出400 Bad Request。

只需在您的表单中添加以下代码即可手动为密钥添加CSRF输入字段,Yii2将接受数据提交:

<?php

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

?>

注意:这是针对高级模板的。从长远来看,我建议不要使用基于短标签的框架,因为PHPers会知道这是一个诅咒。