11<?php
22namespace Slim \Extras \Middleware ;
33
4- /**
5- * CsrfGuard
6- *
7- * This middleware provides protection from CSRF attacks
8- * USAGE
9- *
10- * // Adding middleware
11- * $app = new Slim();
12- * $app->add(new CsrfGuard());
13- *
14- * // Setting token in view
15- * <input type="hidden" name="<?=$csrf_key?>" value="<?=$csrf_token?>">
16- *
17- * @author Mikhail Osher, https://github.com/miraage
18- * @version 1.0
19- */
204class CsrfGuard extends \Slim \Middleware
215{
226 /**
23- * Request key
24- *
25- * @var string
26- */
27- protected $ key ;
7+ * CSRF token key name.
8+ *
9+ * @var string
10+ */
11+ protected $ key ;
2812
2913 /**
30- * Constructor
31- *
32- * @param string $key Request key
33- */
34- public function __construct ($ key = 'csrf_token ' )
35- {
36- // Validate key (i won't use htmlspecialchars)
37- if (!is_string ($ key ) || empty ($ key ) || preg_match ('/[^a-zA-Z0-9\-\_]/ ' , $ key )) {
38- throw new OutOfBoundsException ('Invalid key ' . $ key );
39- }
14+ * CSRF graceful.
15+ *
16+ * @var string
17+ */
18+ protected $ graceful ;
4019
41- $ this ->key = $ key ;
42- }
20+ /**
21+ * Constructor.
22+ *
23+ * @param boolean $graceful If true then destroy the session (graceful), otherwise halt the application (ungraceful).
24+ * @param string $key The CSRF token key name.
25+ * @return void
26+ */
27+ public function __construct ($ graceful = false , $ key = 'csrf_token ' )
28+ {
29+ if (! is_string ($ key ) || empty ($ key ) || preg_match ('/[^a-zA-Z0-9\-\_]/ ' , $ key )) {
30+ throw new \OutOfBoundsException ('Invalid CSRF token key " ' . $ key . '" ' );
31+ }
4332
44- /**
45- * Call middleware
46- */
47- public function call ()
48- {
49- // Attach as hook
50- $ this ->app ->hook ('slim.before ' , array ($ this , 'check ' ));
33+ $ this ->key = $ key ;
34+ $ this ->graceful = (bool ) $ graceful ;
35+ }
5136
52- // Call next middleware
53- $ this ->next ->call ();
54- }
37+ /**
38+ * Call middleware.
39+ *
40+ * @return void
41+ */
42+ public function call ()
43+ {
44+ // Attach as hook.
45+ $ this ->app ->hook ('slim.before ' , array ($ this , 'check ' ));
5546
56- /**
57- * Check token
58- */
59- public function check ()
60- {
61- // Create token
62- if (session_id () !== "" ) {
63- if (!isset ($ _SESSION [$ this ->key ])) {
64- $ _SESSION [$ this ->key ] = sha1 (serialize ($ _SERVER ) . rand (0 , 0xffffffff ));
65- }
66- } else {
67- throw new Exception ( "Session are required to use CSRF Guard " );
68- }
69- $ token = $ _SESSION [$ this ->key ];
47+ // Call next middleware.
48+ $ this ->next ->call ();
49+ }
50+
51+ /**
52+ * Check CSRF token is valid.
53+ * Note: Also checks POST data to see if a Moneris RVAR CSRF token exists.
54+ *
55+ * @return void
56+ */
57+ public function check () {
58+ // Check sessions are enabled.
59+ if (session_id () === '' ) {
60+ throw new \Exception ('Sessions are required to use the CSRF Guard middleware. ' );
61+ }
62+
63+ if (! isset ($ _SESSION [$ this ->key ])) {
64+ $ _SESSION [$ this ->key ] = sha1 (serialize ($ _SERVER ) . rand (0 , 0xffffffff ));
65+ }
66+
67+ $ token = $ _SESSION [$ this ->key ];
7068
71- // Validate
72- if (in_array ($ this ->app ->request ()->getMethod (), array ('POST ' , 'PUT ' , 'DELETE ' ))) {
73- $ usertoken = $ this ->app ->request ()->post ($ this ->key );
74- if ($ token !== $ usertoken ) {
75- $ this ->app ->halt (400 , 'Missing token ' );
69+ // Validate the CSRF token.
70+ if (in_array ($ this ->app ->request ()->getMethod (), array ('POST ' , 'PUT ' , 'DELETE ' ))) {
71+ $ userToken = $ this ->app ->request ()->post ($ this ->key );
72+ if ($ token !== $ userToken ) {
73+ if (! $ this ->graceful ) {
74+ $ this ->app ->halt (400 , 'Invalid or missing CSRF token. ' );
75+ } else {
76+ session_destroy ();
77+ }
7678 }
77- }
79+ }
7880
79- // Assign to view
80- $ this ->app ->view ()->appendData (array (
81- 'csrf_key ' => $ this ->key ,
82- 'csrf_token ' => $ token ,
83- ));
84- }
85- }
81+ // Assign CSRF token key and value to view.
82+ $ this ->app ->view ()->appendData (array (
83+ 'csrf_key ' => $ this ->key ,
84+ 'csrf_token ' => $ token ,
85+ ));
86+ }
87+ }
0 commit comments