CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.8 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.8
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • BodyParserMiddleware
  • CsrfProtectionMiddleware
  • EncryptedCookieMiddleware
  • SecurityHeadersMiddleware
  1: <?php
  2: /**
  3:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4:  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5:  *
  6:  * Licensed under The MIT License
  7:  * For full copyright and license information, please see the LICENSE.txt
  8:  * Redistributions of files must retain the above copyright notice.
  9:  *
 10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 11:  * @link          http://cakephp.org CakePHP(tm) Project
 12:  * @since         3.5.0
 13:  * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 14:  */
 15: namespace Cake\Http\Middleware;
 16: 
 17: use Cake\Http\Cookie\Cookie;
 18: use Cake\Http\Exception\InvalidCsrfTokenException;
 19: use Cake\Http\Response;
 20: use Cake\Http\ServerRequest;
 21: use Cake\I18n\Time;
 22: use Cake\Utility\Hash;
 23: use Cake\Utility\Security;
 24: 
 25: /**
 26:  * Provides CSRF protection & validation.
 27:  *
 28:  * This middleware adds a CSRF token to a cookie. The cookie value is compared to
 29:  * request data, or the X-CSRF-Token header on each PATCH, POST,
 30:  * PUT, or DELETE request.
 31:  *
 32:  * If the request data is missing or does not match the cookie data,
 33:  * an InvalidCsrfTokenException will be raised.
 34:  *
 35:  * This middleware integrates with the FormHelper automatically and when
 36:  * used together your forms will have CSRF tokens automatically added
 37:  * when `$this->Form->create(...)` is used in a view.
 38:  */
 39: class CsrfProtectionMiddleware
 40: {
 41:     /**
 42:      * Default config for the CSRF handling.
 43:      *
 44:      *  - `cookieName` The name of the cookie to send.
 45:      *  - `expiry` A strotime compatible value of how long the CSRF token should last.
 46:      *    Defaults to browser session.
 47:      *  - `secure` Whether or not the cookie will be set with the Secure flag. Defaults to false.
 48:      *  - `httpOnly` Whether or not the cookie will be set with the HttpOnly flag. Defaults to false.
 49:      *  - `field` The form field to check. Changing this will also require configuring
 50:      *    FormHelper.
 51:      *
 52:      * @var array
 53:      */
 54:     protected $_defaultConfig = [
 55:         'cookieName' => 'csrfToken',
 56:         'expiry' => 0,
 57:         'secure' => false,
 58:         'httpOnly' => false,
 59:         'field' => '_csrfToken',
 60:     ];
 61: 
 62:     /**
 63:      * Configuration
 64:      *
 65:      * @var array
 66:      */
 67:     protected $_config = [];
 68: 
 69:     /**
 70:      * Callback for deciding whether or not to skip the token check for particular request.
 71:      *
 72:      * CSRF protection token check will be skipped if the callback returns `true`.
 73:      *
 74:      * @var callable|null
 75:      */
 76:     protected $whitelistCallback;
 77: 
 78:     /**
 79:      * Constructor
 80:      *
 81:      * @param array $config Config options. See $_defaultConfig for valid keys.
 82:      */
 83:     public function __construct(array $config = [])
 84:     {
 85:         $this->_config = $config + $this->_defaultConfig;
 86:     }
 87: 
 88:     /**
 89:      * Checks and sets the CSRF token depending on the HTTP verb.
 90:      *
 91:      * @param \Cake\Http\ServerRequest $request The request.
 92:      * @param \Cake\Http\Response $response The response.
 93:      * @param callable $next Callback to invoke the next middleware.
 94:      * @return \Cake\Http\Response A response
 95:      */
 96:     public function __invoke(ServerRequest $request, Response $response, $next)
 97:     {
 98:         if ($this->whitelistCallback !== null
 99:             && call_user_func($this->whitelistCallback, $request) === true
100:         ) {
101:             return $next($request, $response);
102:         }
103: 
104:         $cookies = $request->getCookieParams();
105:         $cookieData = Hash::get($cookies, $this->_config['cookieName']);
106: 
107:         if (strlen($cookieData) > 0) {
108:             $params = $request->getAttribute('params');
109:             $params['_csrfToken'] = $cookieData;
110:             $request = $request->withAttribute('params', $params);
111:         }
112: 
113:         $method = $request->getMethod();
114:         if ($method === 'GET' && $cookieData === null) {
115:             $token = $this->_createToken();
116:             $request = $this->_addTokenToRequest($token, $request);
117:             $response = $this->_addTokenCookie($token, $request, $response);
118: 
119:             return $next($request, $response);
120:         }
121:         $request = $this->_validateAndUnsetTokenField($request);
122: 
123:         return $next($request, $response);
124:     }
125: 
126:     /**
127:      * Set callback for allowing to skip token check for particular request.
128:      *
129:      * The callback will receive request instance as argument and must return
130:      * `true` if you want to skip token check for the current request.
131:      *
132:      * @param callable $callback A callable.
133:      * @return $this
134:      */
135:     public function whitelistCallback(callable $callback)
136:     {
137:         $this->whitelistCallback = $callback;
138: 
139:         return $this;
140:     }
141: 
142:     /**
143:      * Checks if the request is POST, PUT, DELETE or PATCH and validates the CSRF token
144:      *
145:      * @param \Cake\Http\ServerRequest $request The request object.
146:      * @return \Cake\Http\ServerRequest
147:      */
148:     protected function _validateAndUnsetTokenField(ServerRequest $request)
149:     {
150:         if (in_array($request->getMethod(), ['PUT', 'POST', 'DELETE', 'PATCH'], true) || $request->getData()) {
151:             $this->_validateToken($request);
152:             $body = $request->getParsedBody();
153:             if (is_array($body)) {
154:                 unset($body[$this->_config['field']]);
155:                 $request = $request->withParsedBody($body);
156:             }
157:         }
158: 
159:         return $request;
160:     }
161: 
162:     /**
163:      * Create a new token to be used for CSRF protection
164:      *
165:      * @return string
166:      */
167:     protected function _createToken()
168:     {
169:         return hash('sha512', Security::randomBytes(16), false);
170:     }
171: 
172:     /**
173:      * Add a CSRF token to the request parameters.
174:      *
175:      * @param string $token The token to add.
176:      * @param \Cake\Http\ServerRequest $request The request to augment
177:      * @return \Cake\Http\ServerRequest Modified request
178:      */
179:     protected function _addTokenToRequest($token, ServerRequest $request)
180:     {
181:         $params = $request->getAttribute('params');
182:         $params['_csrfToken'] = $token;
183: 
184:         return $request->withAttribute('params', $params);
185:     }
186: 
187:     /**
188:      * Add a CSRF token to the response cookies.
189:      *
190:      * @param string $token The token to add.
191:      * @param \Cake\Http\ServerRequest $request The request to validate against.
192:      * @param \Cake\Http\Response $response The response.
193:      * @return \Cake\Http\Response $response Modified response.
194:      */
195:     protected function _addTokenCookie($token, ServerRequest $request, Response $response)
196:     {
197:         $expiry = new Time($this->_config['expiry']);
198: 
199:         $cookie = new Cookie(
200:             $this->_config['cookieName'],
201:             $token,
202:             $expiry,
203:             $request->getAttribute('webroot'),
204:             '',
205:             (bool)$this->_config['secure'],
206:             (bool)$this->_config['httpOnly']
207:         );
208: 
209:         return $response->withCookie($cookie);
210:     }
211: 
212:     /**
213:      * Validate the request data against the cookie token.
214:      *
215:      * @param \Cake\Http\ServerRequest $request The request to validate against.
216:      * @return void
217:      * @throws \Cake\Http\Exception\InvalidCsrfTokenException When the CSRF token is invalid or missing.
218:      */
219:     protected function _validateToken(ServerRequest $request)
220:     {
221:         $cookies = $request->getCookieParams();
222:         $cookie = Hash::get($cookies, $this->_config['cookieName']);
223:         $post = Hash::get($request->getParsedBody(), $this->_config['field']);
224:         $header = $request->getHeaderLine('X-CSRF-Token');
225: 
226:         if (!$cookie) {
227:             throw new InvalidCsrfTokenException(__d('cake', 'Missing CSRF token cookie'));
228:         }
229: 
230:         if (!Security::constantEquals($post, $cookie) && !Security::constantEquals($header, $cookie)) {
231:             throw new InvalidCsrfTokenException(__d('cake', 'CSRF token mismatch.'));
232:         }
233:     }
234: }
235: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs