When I try to login, the request gets blackholed by teh Security
component. How can I make it work right?
I have a simple login form
<div class="container container-login">
<h2><?php echo __('Login'); ?></h2>
<div class="wrap-form-signin">
<?php
echo $this->Form->create('User', array('action' => 'login', 'class' => 'form-signin'));
echo $this->Form->input('username', array('label' => '', 'placeholder' => __('Email')));
echo $this->Form->input('password', array('label' => '', 'placeholder' => __('Password')));
echo $this->Form->submit(__('Login'));
echo $this->Form->end();
?>
</div>
</div>
The controller action goes like this:
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Session->setFlash(__('Username or password is incorrect'), 'default', array(), 'auth');
}
}
}
And the Security
component is included in AppController
public $components = array('Security', ... );
In the error.log I get:
2013-03-29 13:40:58 Error: [BadRequestException] The request has been black-holed
Request URL: /users/login
Stack Trace:
#0 C:\wamp\www\cdx\lib\Cake\Controller\Component\SecurityComponent.php(234): SecurityComponent->blackHole(Object(UsersController), 'auth')
#1 [internal function]: SecurityComponent->startup(Object(UsersController))
#2 C:\wamp\www\cdx\lib\Cake\Utility\ObjectCollection.php(131): call_user_func_array(Array, Array)
#3 [internal function]: ObjectCollection->trigger(Object(CakeEvent))
#4 C:\wamp\www\cdx\lib\Cake\Event\CakeEventManager.php(247): call_user_func(Array, Object(CakeEvent))
#5 C:\wamp\www\cdx\lib\Cake\Controller\Controller.php(670): CakeEventManager->dispatch(Object(CakeEvent))
#6 C:\wamp\www\cdx\lib\Cake\Routing\Dispatcher.php(183): Controller->startupProcess()
#7 C:\wamp\www\cdx\lib\Cake\Routing\Dispatcher.php(161): Dispatcher->_invoke(Object(UsersController), Object(CakeRequest), Object(CakeResponse))
#8 C:\wamp\www\cdx\app\webroot\index.php(92): Dispatcher->dispatch(Object(CakeRequest), Object(CakeResponse))
#9 {main}
How can I find what is making my request go to black hole?
When I tried to use a custom blackhole handler, the type of the error was auth
. But that's all the information I can get
My version of CakePHP is 2.3.1
EDIT:
The login works well without the Security
component. After adding it to the AppController
, the login stops working.
EDIT2: I don't have any data[_Token][key]
fields in the form
EDIT3 THE SOLLUTION: Someone from my team has overriden the HTMLHelper class and it missed "hiddenblock" in the _tags array, which resulted in missing _Token fields. For details, see mine and thaJeztah's answers along with the comments bellow them
Answering because I cannot comment. Have you tried adding a callback to the Security component and see what exactly it is generating?
Look at: http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#handling-blackhole-callbacks
What exactly do you plan on using the Security component for? What are you trying to prevent?
Have you tried using Session tokens instead of per form tokens? http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#csrf-protection
I had the same issue with an user login form both from the login.ctp and using it from another view as an element and managed to fix this by closing the form with $this->Form->end() otherwise it will not add the hidden inputs form the Token.... Hope this help.
In what order did you add your components? The security-component should be put before other components that handle form-data in their
startup()
:"If you are using Security component’s form protection features and other components that process form data in their startup() callbacks, be sure to place Security Component before those components in your $components array."
Security
Because the AuthComponent does handle form data inside the
startup()
, I think this applies, so be sure that the SecurityComponent is before the AuthComponent in your $components array;Update
The 'final' answer as posted by the OP made clear that this question could not have been answered. as it turned out, somebody in the team made modifications to the HtmlHelper, causing it to not output 'hidden' blocks, and therefore not outputting the CSRF token.
In normal situations, you should never make modifications to the CakePHP Framework files themselves. CakePHP offers ways to override its functionality (including Helpers) without modifying the 'core' CakePHP files.
Why modifying CakePHP files is bad
Consider, for example, a car. What if a mechanic didn't like the design and decided to 'swap' the brake and accelerator pedals?
Of course, the car is still able to drive if you we're aware of this modification. However, without this important information, any other driver would definitely crash (and wonder what the heck just happened!?)
If the default behavior of the framework doesn't fit your needs, extend those classes. Do not modify the framework files themselves (unless there really is no other option). If modifications to the framework are absolutely nescessary, be sure to discuss this with the team and write documentation on the changes that have been made.
Keep in mind that it will no longer be possible to update the framework to a newer version, without applying the same modifications to the updated version as well. Again, if the changes have not been documented, somebody might update CakePHP and destroy your modifications.
Also, if you override or modify CakePHP, make sure that the overrides are compatible with the default behavior of CakePHP and the unit tests of CakePHP still run correctly (or create new Unit Tests for the modifications)
Using 'customised' Helpers in CakePHP
If you need to customise the CakePHP Helpers (or other components), there are various options to do so without modifying the CakePHP files;
1. Extend the Helper
Then, use your Helper the regular way:
2. 'Drop-in' replacement - use an alias (CakePHP > 2.3)
Since CakePHP 2.3 its possible to use an alias for a Helper. This functionality can be used in situations where (for example) two Helpers with the same name exist in your Application (e.g. Plugin.HtmlHelper).
Also, this allows you override a CakePHP Helper with your own Helper. See the documentation here: Using and Configuring Helpers
Be aware that this will override the Helper everywhere in your application!
Now,
$this->Html
will actually refer to theAwesomeHtmlHelper
in your views:Will output your 'enhanced' table headers
EDIT: There was actually no error on the
line, it was rather a team member modification to the
HtmlHelper
I didn't know about that prevented_Token
inputs to be printed in the page. The main issue remains, and it is the absence ofdata[_Token][key]
input in the form, which I had to addI finally found out what was the problem. There were no
_Token
fields because of a possible erorr inFormHelper
class. I had to edit thesecure
method that looked like this:This method returned an empty string. So instead of returning the result of
useTag
I simply returned$out
.One more thing I had to do is add the
data[_Token][key]
field. In the end, the method looks like this:It is difficult to test with the info you provided, but I would try to change the form create call into this:
echo $this->Form->create('User', array('url' => array('controller' => 'users', 'action' => 'login'), 'class' => 'form-signin'));
auth
type of error indicates a form validation error, or a controller/action mismatch error. That could happen if the page where you display your form is NOT/users/login
, as cross controller communication is blackholed when using Security component. Hope it helpsEdit: The validation error could also point to fact that you have not defined
username
for Auth component, checkout cookbook