zoukankan      html  css  js  c++  java
  • yii 2 局部关闭 CSRF 拦截

    最近在拿 yii 2.0 开发ajax提交,在 post 请求接口时,提示数据无法验证,于是查询 yii 错误日志,发现错误为

    exception ‘yiiwebBadRequestHttpException’ with message ‘Unable to verify your data submission

    于是查看源代码,yii 2.0 在 我们继承的顶级 controller 中,有下列属性

    /**
     * @var boolean whether to enable CSRF validation for the actions in this controller.
     * CSRF validation is enabled only when both this property and [[Request::enableCsrfValidation]] are true.
    */
     public $enableCsrfValidation = true;

    106 行的 beforeAction 内,对他做了处理

    ``` public function beforeAction($action) { if (parent::beforeAction($action)) { if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !Yii::$app->getRequest()->validateCsrfToken()) { throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.')); } return true; } else { return false; } }

    ```

    于是找到错误原因:

    yii 2.0 内,对 CSRF 攻击做了处理,会对 post 提交的数据做 token 验证,而微信 post 到我们服务器的代码中,没有带上这个 token ,所以会验证失败

    解决方法:

    1、在我们的控制器里面,加上这行属性,设置为 false

    public $enableCsrfValidation = false;

    你还可以直接修改顶层控制器的 $enableCsrfValidation ,但是不推荐这样做!

    2、关于如何在单独的action中关闭Csrf验证

    由于Yii2 Controller Csrf验证是在beforeAction中完成的,所以在action中指定
    $this->enableCsrfValidation = false;
    不能实现局部关闭Csrf。

    如何实现

    新建一个Behavior

    <?php
    use Yii;
    use yiibaseActionEvent;
    use yiibaseBehavior;
    use yiiwebController;
    
    
    class NoCsrf extends Behavior
    {
        public $actions = [];
        public $controller;
        public function events()
        {
            return [Controller::EVENT_BEFORE_ACTION => 'beforeAction'];
        }
        public function beforeAction($event)
        {
            $action = $event->action->id;
            if(in_array($action, $this->actions)){
                $this->controller->enableCsrfValidation = false;
            }
        }    
    }

    然后在Controller中添加Behavior

    ?php
    
        public function behaviors()
        {
            return [
                'csrf' => [
                    'class' => NoCsrf::className(),
                    'controller' => $this,
                    'actions' => [
                        'action-name'
                    ]
                ]
            ];
        }

    这样就实现了在action中关闭Csrf而不是在整个Controller中关闭。

  • 相关阅读:
    Hammer.js手势库 安卓4.0.4上的问题
    大前端晋级系列之-单一职责原则
    大前端晋级系列之-策略模式
    为什么MVC不是一种设计模式
    解读sencha touch移动框架的核心架构(二)
    解读sencha touch移动框架的核心架构(一)
    大型 JavaScript 应用架构中的模式
    jQuery2.0.3源码分析系列之(29) 窗口尺寸
    jQuery2.0.3源码分析系列(28) 元素大小
    开放封闭原则(Open Closed Principle)
  • 原文地址:https://www.cnblogs.com/yhdsir/p/5202796.html
Copyright © 2011-2022 走看看