Opposite of requireSecure in CakePHP
CakePHP在SecurityComponent中具有requireSecure函数。在传递敏感信息(例如信用卡号)时,我使用它来强制使用SSL。
问题:
- 有requireNonSecure函数吗?
- 如果没有requireNonSecure函数,是否可以在不修改原始文件的情况下将功能扩展/添加到CakePHP的核心文件中?
我需要requireNonSecure函数,因为我的某些页面上嵌入了只能在我们的域名上播放的视频。使用SSL时,视频托管服务无法识别我们的域名,也无法播放视频。
这是控制器的beforeFilter中的一些代码:
1 2 3 4 5 6 7 8 9 | function beforeFilter() { parent::beforeFilter(); $this->Security->validatePost = false; // disable CSRF protection $this->Security->blackHoleCallback = 'forceSSL'; $this->Security->requireSecure('pay', 'index'); $this->Auth->allow('index'); } |
这是app_controller.php
中的回调
1 2 3 4 5 6 7 8 | function forceSSL() { $redirect = ''; if (!empty($this->params['url']['redirect'])) { $redirect = '?redirect=' . $this->params['url']['redirect']; } $this->redirect('https://' . rtrim(env('SERVER_NAME'), '/') . $this->here . $redirect); } |
一个解决方案是将一个函数附加到beforeFilter上,如下所示:
在控制器中:
1 2 3 4 5 6 7 8 9 | function beforeFilter() { parent::beforeFilter(); // Require non secure (http) for video action $this->requireNonSecure('video'); // ... other code here } |
在app_controller.php中:
1 2 3 4 5 6 7 8 9 10 | function requireNonSecure() { $requireNonSecure = array_map('strtolower', func_get_args()); if (in_array(strtolower($this->action), $requireNonSecure) || $requireNonSecure == array('*')) { if ($this->RequestHandler->isSSL()) { $this->redirect('http://' . rtrim(env('SERVER_NAME'), '/') . $this->here); return; } } } |
此解决方案添加到SecurityComponent。它应该可以工作,但是如果同时设置了requireSecure和requireNonSecure,则存在重定向循环的风险。
SecurityPlusComponent:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | class SecurityPlusComponent extends SecurityComponent { /** * List of actions that do not require an SSL-secured connection * * @var array * @access public * @see SecurityPlusComponent::requireNonSecure() */ var $requireSecure = array(); /** * Component startup. All security checking happens here. * * @param object $controller Instantiating controller * @access public */ function startup(&$controller) { $this->_action = strtolower($controller->action); $this->_methodsRequired($controller); $this->_secureRequired($controller); $this->_nonSecureRequired($controller); $this->_authRequired($controller); $this->_loginRequired($controller); $isPost = ($this->RequestHandler->isPost() || $this->RequestHandler->isPut()); $isRequestAction = ( !isset($controller->params['requested']) || $controller->params['requested'] != 1 ); if ($isPost && $isRequestAction && $this->validatePost) { if ($this->_validatePost($controller) === false) { if (!$this->blackHole($controller, 'auth')) { return null; } } } $this->_generateToken($controller); } function requireNonSecure() { $this->_requireMethod('NonSecure', func_get_args()); } /** * Check if access requires non secure connection (http) * * @param object $controller Instantiating controller * @return bool true if secure connection required * @access protected */ function _nonSecureRequired(&$controller) { if (is_array($this->requireNonSecure) && !empty($this->requireNonSecure)) { $requireNonSecure = array_map('strtolower', $this->requireNonSecure); if (in_array($this->_action, $requireNonSecure) || $this->requireNonSecure == array('*')) { if ($this->RequestHandler->isSSL()) { if (!$this->blackHole($controller, 'nonSecure')) { return null; } } } } return true; } } |
已修改的app_controller forceSSL函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | function securityBlackhole($type) { $redirect = ''; if (!empty($this->params['url']['redirect'])) { $redirect = '?redirect=' . $this->params['url']['redirect']; } // Force http (non-SSL) if($type == 'nonSecure') { $this->redirect('http://' . rtrim(env('SERVER_NAME'), '/') . $this->here . $redirect); // Force https (SSL) } else { $this->redirect('https://' . rtrim(env('SERVER_NAME'), '/') . $this->here . $redirect); } } |
将在控制器中这样调用:
1 2 3 4 5 6 7 8 9 10 | function beforeFilter() { parent::beforeFilter(); $this->SecurityPlus->validatePost = false; // disable CSRF protection $this->SecurityPlus->blackHoleCallback = 'securityBlackhole'; $this->SecurityPlus->requireSecure('pay', 'index'); $this->SecurityPlus->requireNonSecure('video'); $this->Auth->allow('index'); } |