RequestToken will persist the token for the life of the client session, and generate per-request keys that will match against that token. Using these token/key pairs in forms and other non-idempotent requests will help you secure your application against cross-site request forgeries, or CSRF attacks. ### Example views/comments/add.html.php: ... form->create($object); ?> security->requestToken(); ?> Other fields... form->end(); ?> controllers/CommentsController.php: public function add() { if ($this->request->data && !RequestToken::check($this->request)) { Key didn't match the CSRF token. Regenerate the session token and prompt the user to retry the form submission. RequestToken::get(array('regenerate' => true)); return; } Handle a normal request... }
See also: lithium\template\helper\Security::requestToken()
示例#1
0
 protected function _init()
 {
     parent::_init();
     # Check CSRF forgery signature
     if ($this->request->data and !RequestToken::check($this->request)) {
         throw new \Exception('Invalid request token.');
     }
     if (isset($this->request->data['security']['token'])) {
         unset($this->request->data['security']);
     }
     # Load active user
     $current_identity = Auth::check('any');
     if (is_object($current_identity)) {
         $u = $current_identity->getUser();
         $this->CURRENT_USER = $u;
     }
     $this->set(array('CURRENT_USER' => $this->CURRENT_USER));
 }
 /**
  * Tests extracting a key from a `Request` object and matching it against a token.
  */
 public function testTokenFromRequestObject()
 {
     $request = new Request(array('data' => array('security' => array('token' => RequestToken::key()))));
     $this->assertTrue(RequestToken::check($request));
 }
 /**
  * Remove directory or file
  * 
  * html:method POST
  */
 public function remove()
 {
     if ($this->request->is('ajax') && $this->request->data) {
         if (!RequestToken::check($this->request->data['token'])) {
             return $this->render(array('json' => array('regenerate' => true)));
         }
         $success = true;
         $errors = array();
         foreach ($this->request->data['selected'] as $path) {
             $remove = Location::remove($path);
             if (!$remove) {
                 $errors[] = array('error' => "<strong>{$path}</strong> not removed");
             }
             if (!$copy && $success) {
                 $success = false;
             }
         }
         return $this->render(array('json' => compact('success', 'errors')));
     }
     return $this->redirect($this->_link);
 }
示例#4
0
 /**
  * Allows a user to update their own profile.
  *
  */
 public function update()
 {
     if (!$this->request->user) {
         FlashMessage::write('You must be logged in to do that.', 'default');
         return $this->redirect('/');
     }
     // Special rules for user creation (includes unique e-mail)
     $rules = array('email' => array(array('notEmpty', 'message' => 'E-mail cannot be empty.'), array('email', 'message' => 'E-mail is not valid.'), array('uniqueEmail', 'message' => 'Sorry, this e-mail address is already registered.')));
     // Get the document from the db to edit
     $conditions = array('_id' => $this->request->user['_id']);
     $document = User::find('first', array('conditions' => $conditions));
     $existingProfilePic = !empty($document->profilePicture) ? $document->profilePicture : false;
     // Redirect if invalid user...This should not be possible.
     if (empty($document)) {
         FlashMessage::write('You must be logged in to do that.', 'default');
         return $this->redirect('/');
     }
     // If data was passed, set some more data and save
     if ($this->request->data) {
         // CSRF
         if (!RequestToken::check($this->request)) {
             RequestToken::get(array('regenerate' => true));
         } else {
             $now = new MongoDate();
             $this->request->data['modified'] = $now;
             // Add validation rules for the password IF the password and password_confirm field were passed
             if (isset($this->request->data['password']) && isset($this->request->data['passwordConfirm']) && (!empty($this->request->data['password']) && !empty($this->request->data['passwordConfirm']))) {
                 $rules['password'] = array(array('notEmpty', 'message' => 'Password cannot be empty.'), array('notEmptyHash', 'message' => 'Password cannot be empty.'), array('moreThanFive', 'message' => 'Password must be at least 6 characters long.'));
                 // ...and of course hash the password
                 $this->request->data['password'] = Password::hash($this->request->data['password']);
             } else {
                 // Otherwise, set the password to the current password.
                 $this->request->data['password'] = $document->password;
             }
             // Ensure the unique e-mail validation rule doesn't get in the way when editing users
             // So if the user being edited has the same e-mail address as the POST data...
             // Change the e-mail validation rules
             if (isset($this->request->data['email']) && $this->request->data['email'] == $document->email) {
                 $rules['email'] = array(array('notEmpty', 'message' => 'E-mail cannot be empty.'), array('email', 'message' => 'E-mail is not valid.'));
             }
             // Set the pretty URL that gets used by a lot of front-end actions.
             // Pass the document _id so that it doesn't change the pretty URL on an update.
             $this->request->data['url'] = $this->_generateUrl($document->_id);
             // Do not let roles or user active status to be adjusted via this method.
             if (isset($this->request->data['role'])) {
                 unset($this->request->data['role']);
             }
             if (isset($this->request->data['active'])) {
                 unset($this->request->data['active']);
             }
             // Profile Picture
             if (isset($this->request->data['profilePicture']['error']) && $this->request->data['profilePicture']['error'] == UPLOAD_ERR_OK) {
                 $rules['profilePicture'] = array(array('notTooLarge', 'message' => 'Profile picture cannot be larger than 250px in either dimension.'), array('invalidFileType', 'message' => 'Profile picture must be a jpg, png, or gif image.'));
                 list($width, $height) = getimagesize($this->request->data['profilePicture']['tmp_name']);
                 // Check file dimensions first.
                 // TODO: Maybe make this configurable.
                 if ($width > 250 || $height > 250) {
                     $this->request->data['profilePicture'] = 'TOO_LARGE.jpg';
                 } else {
                     // Save file to gridFS
                     $ext = substr(strrchr($this->request->data['profilePicture']['name'], '.'), 1);
                     switch (strtolower($ext)) {
                         case 'jpg':
                         case 'jpeg':
                         case 'png':
                         case 'gif':
                         case 'png':
                             $gridFile = Asset::create(array('file' => $this->request->data['profilePicture']['tmp_name'], 'filename' => (string) uniqid(php_uname('n') . '.') . '.' . $ext, 'fileExt' => $ext));
                             $gridFile->save();
                             break;
                         default:
                             $this->request->data['profilePicture'] = 'INVALID_FILE_TYPE.jpg';
                             //exit();
                             break;
                     }
                     // If file saved, set the field to associate it (and remove the old one - gotta keep it clean).
                     if (isset($gridFile) && $gridFile->_id) {
                         if ($existingProfilePic && substr($existingProfilePic, 0, 4) != 'http') {
                             $existingProfilePicId = substr($existingProfilePic, 0, -strlen(strrchr($existingProfilePic, '.')));
                             // Once last check...This REALLY can't be empty, otherwise it would remove ALL assets!
                             if (!empty($existingProfilePicId)) {
                                 Asset::remove(array('_id' => $existingProfilePicId));
                             }
                         }
                         // TODO: Maybe allow saving to disk or S3 or CloudFiles or something. Maybe.
                         $this->request->data['profilePicture'] = (string) $gridFile->_id . '.' . $ext;
                     } else {
                         if ($this->request->data['profilePicture'] != 'INVALID_FILE_TYPE.jpg') {
                             $this->request->data['profilePicture'] = null;
                         }
                     }
                 }
             } else {
                 $this->request->data['profilePicture'] = null;
             }
             // Save
             if ($document->save($this->request->data, array('validate' => $rules))) {
                 FlashMessage::write('You have successfully updated your user settings.', 'default');
                 $this->redirect(array('library' => 'li3b_users', 'controller' => 'users', 'action' => 'update'));
             } else {
                 $this->request->data['password'] = '';
                 FlashMessage::write('There was an error trying to update your user settings, please try again.', 'default');
             }
         }
     }
     $this->set(compact('document'));
 }
示例#5
0
文件: CSRF.php 项目: qujian/rwe
 /**
  * 验证token
  * @param string $token
  * @return boolean
  */
 public static function check($token)
 {
     $check = RequestToken::check($token);
     self::generate(array('regenerate' => true));
     return $check;
 }