donvo24600 2012-03-21 01:56
浏览 138

控制器中的过滤方法

I want to create a filter for my add, update, and delete actions in my controllers to automatically check if they

  1. were called in a POST, as opposed to GET or some other method
  2. and have the pageInstanceIDs which I set in the forms on my views
    • protects against xss
    • protects against double submission of a form
      • from submit button double click
      • from back button pressed after a submision
      • from a url being saved or bookmarked

Currently I extended \lithium\action\Controller using an AppController and have my add, update, and delete actions defined in there. I also have a boolean function in my AppController that checks if the appropriate pageInstanceIDs are in session or not.

Below is my code:

public function isNotPostBack() {

    // pull in the session
    $pageInstanceIDs = Session::read('pageInstanceIDs');
    $pageInstanceID = uniqid('', true);
    $this->set(compact('pageInstanceID'));
    $pageInstanceIDs[] = $pageInstanceID;
    Session::write('pageInstanceIDs', $pageInstanceIDs);

    // checks if this is a save operation
    if ($this->request->data){

        $pageInstanceIDs = Session::read('pageInstanceIDs');
        $pageIDIndex = array_search($this->request->data['pageInstanceID'], $pageInstanceIDs);

        if ($pageIDIndex !== false) {
            // remove the key
            unset($pageInstanceIDs[$pageIDIndex]);
            Session::write('pageInstanceIDs', $pageInstanceIDs);

            return true;

        }
        else
            return false;

    } else {
        return true;
    }

}

public function add() {
    if (!$this->request->is('post') && exist($this->request->data())) {
        $msg = "Add can only be called with http:post.";
        throw new DispatchException($msg);
    }

}

Then in my controllers I inherit from AppController and implement the action like so:

public function add() {
    parent::add();
    if (parent::isNotPostBack()){
        //do work

    }
    return $this->render(array('layout' => false));

}

which will ensure that the form used a POST and was not double submitted (back button or click happy users). This also helps protect against XSS.

I'm aware there is a plugin for this, but I want to implement this as a filter so that my controller methods are cleaner. Implented this way, the only code in my actions are the //do work portion and the return statement.

  • 写回答

4条回答 默认 最新

  • dtjpnd7517 2012-03-21 02:21
    关注

    You should probably start with a filter on lithium\action\Dispatcher::run() here is some pseudo code. Can't help too much without seeing your parent::isNotPostBack() method but this should get you on the right track.

    <?php
    use lithium\action\Dispatcher;
    
    Dispatcher::applyFilter('run', function($self, $params, $chain) {
        $request = $params['request'];
    
        // Request method is in $request->method
        // Post data is in $request->data
    
        if($not_your_conditions) {
            return new Response(); // set up your custom response
        }
    
        return $chain->next($self, $params, $chain); // to continue on the path of execution
    });
    
    评论

报告相同问题?

悬赏问题

  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程
  • ¥15 redis-full-check比较 两个集群的数据出错
  • ¥15 Matlab编程问题
  • ¥15 训练的多模态特征融合模型准确度很低怎么办
  • ¥15 kylin启动报错log4j类冲突