I have used ACL in CakePHP 1.3 without a single issue, after 2 weeks of bitter frustrations it still does not work in CakePHP 2.0.
I have followed the Cake ACL tutorial EXACTLY, but nothing happens. All Aros are in correctly, same for ACOS and permissions.
After all this, I can enter all denied actions without a problem.
Hereby my AppController:
public $components = array('Acl','Auth'=> array(
'authenticate' => array(
'Actions',
'Form' => array(
'fields' => array('username' => 'email')
),
)
), 'Session', 'MathCaptcha', 'RequestHandler');
In my BeforeFilter:
$this->Auth->actionPath = 'controllers';
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'pages', 'action' => 'home');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'profile');
$this->Auth->allow('display');
Does someone have an idea what goes wrong. Thanks!
In CakePHP 2.0 I've made this way:
app/Controller/AppController.php
class AppController extends Controller {
public $components = array(
// others components...
'Session',
'Acl',
'Auth'=> array(
// Setting AUTHORIZATION "What can you do?"
'authorize' => array(
'Actions' => array(
'actionPath' => 'controllers'
)
),
// Setting AUTHENTICATION "Who are you?"
'authenticate' => array(
'Form' => array(
'fields' => array(
'username' => 'email', 'password' => 'password'
)
)
)
)
);
// other stuffs...
With this aproach, ACL will make all dirty job. Is not necessary to check permitions, as you probably know.
I believe you are Ok about AROs and ACOs, not big deal. Just in case:
http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/simple-acl-controlled-application.html#simple-acl-controlled-application
The CakeBook for 2.0 shows a Console plugin called AclExtras that build your ACOs. Your AROs will be built as users and groups are added/deleted. I've used this plugin to generate AROs regarding my already filled tables: http://www.alaxos.ch/blaxos/pages/view/plugin_acl. This works fos 1.3, but there is a beta version for 2.0 that works ok.
After that, You must set up permitions. Manually (or from Console) as this links describes: http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/part-two.html#setting-up-permissions. Or visually with Alaxos's Plugin.
I hope this help! It's worked for me. I'm using CakePHP 2.0.2
The Auth component changed quite a bit from CakePHP 1.3 to 2.0. I bumped into similar issues migrating an app from 1.3 to 2.0. I found that setting the authorize option was where I needed to make my change:
In beforeFilter:
$this->Auth->authorize = array(
'Actions' => array(
'userModel' => 'User',
'actionPath' => 'users'
)
);
The userModel was the model class used in the Aro table. The actionPath is the root level of the actions that Acl checks in the Aco table.
You may also want to deny then allow:
$this->Auth->deny('*');
$this->Auth->allow('display');
Hope this helps.
Related
In my AppController I have this code for the component
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
),
'unauthorizedRedirect' => array(
'controller' => 'member',
'action' => 'index'
)
),
'Session',
'DebugKit.Toolbar'
);
So, unauthorizedRedirect is working fine. I tried to type the URL the user has no access to and fortunately, I am redirected to 'localhost/appname/member/'.
My concern is that, this only applies to one type of logged in user.
Let us say a logged in user tried to access localhost/appname/admin/add_post/. Since only admins have access to that page, the user will be redirected to localhost/appname/member/. What if it's an admin who accessed an unauthorized page? Of course, that admin will have to redirected somewhere, but not to localhost/appname/member/.
How can I solve this?
I believe there are many ways. You are already using the ACL which is one way. Or another "lazy" way to do this is to use the beforeFilter method inside the AppController.
Ok, so after several hours of researching and stuff I was able to come up with a solution.
This is the code for the AppCntroller:
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
),
'unauthorizedRedirect' => false
),
'Session',
'DebugKit.Toolbar'
);
What this does is rather than redirecting the user to another page, it will just show 'error400.ctp'.
Now, we don't want to show the default CakePHP error layout so we still have to edit it or make a custom one.
Create a new file under 'View/Layouts/your_error_file.ctp'. After that, go to 'View/Errors/error_file.ctp' and paste the following code:
$this->layout = 'your_error_file'
I've created a plugin called 'IssueTracker', which is located in app/Plugin/IssueTracker. I've created a Controller called Tickets and it is accessible at www.example.com/issue_tracker/tickets/. But, only for logged in users with the rank 'Admin'.
That wasn't exactly what I was hoping for, so I added in my Plugin/IssueTracker/Controller/TicketsController.php the following:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('index');
}
I hoped that with this piece of code (which I'm using in several other controllers in my app/Controller/ that it would inherit from my AppController.php file. The TicketsController.php file extends the IssueTrackerAppController (like this):
class TicketsController extends IssueTrackerAppController {
//functions goes in here
}
And in my Plugin/Controller folder I've created the file IssueTrackerAppController which extends the AppController.
In my AppController.php file I've allready defined that 'index' and 'view' are public actions. But, for some reason, it doesn't work in my plugin.
Is there something that I'm overseeing? When I access www.example.com/issue_tracker/tickets as a not logged in user (Guest), it tells me that I need to login. If I'm logged in as a user, but not as an Admin, the Auth component won't allow me in and presents the login form.
There should be a way to get Auth working in a plugin, right?
EDIT
Below is the AppController.php snippet where I've configured Auth:
public $components = array(
'Auth' => array(
'loginAction' => array('controller' => 'users', 'action' => 'login', 'plugin' => false),
'loginRedirect' => array('plugin' => false, 'controller' => 'ervaringen', 'action' => 'add'),
'logoutRedirect' => array('plugin' => false, 'controller' => 'ervaringen', 'action' => 'index'),
'authorize' => array('controller'),
'flash' => array(
'element' => 'error',
'key' => 'auth',
'params' => array(
'heading' => 'Waarschuwing!')
),
'authError' => 'Je moet inloggen om deze inhoud te bekijken.',
),
'Session',
'DebugKit.Toolbar'
);
Mystery solved.
After rescanning all the code in the plugin, I noticed that one of my coworkers on the project used $variable = $this->requestAction(link/here/with/id/etc);, which leads towards a controller function. That particular function wasn't allowed in any way by the beforeFilter(), causing a 'function denied' bij the Auth system.
I've added this particular function in $this->Auth->allow('function'); in the beforeFilter() of the plugin and now it is working.
I'm working on my first app w/ CakePHP 2.3 and I'm having an issue where I can login (no auth errors), but my session isn't sticking around so I'm sent back to the login page when the Auth->redirect() is called. I'm sure I'm just missing a setting or have something configured slightly wrong, but I haven't been able to find it.
# core.php
# session record is written the the database, but the same record's id changes w/ every request
Configure::write('Session', array(
'defaults' => 'database',
));
Configure::write('Security.level', 'medium');
I've tried tweaking the various Session.X parameters, but nothing has made any difference. I'm using bcrypt authentication with the following settings in my AppController:
'Auth' => array(
'authenticate' => array(
'Blowfish' => array(
'fields' => array( 'username' => 'email' ),
'scope' => array( 'active' => '1' )
),
),
'authorize' => array( 'Controller' ),
'loginAction' => array( 'admin' => false, 'controller' => 'users', 'action' => 'login' ),
'loginRedirect' => array( 'admin' => true, 'controller' => 'activities', 'action' => 'index' ),
'logoutRedirect' => array( 'admin' => false, 'controller' => 'users', 'action' => 'login' ),
),
What piece am I missing?
UPDATE
Realizing that this is only happening in my dev environment, I compared my Cake config (database, core, bootstrap) and php.ini values -- no differences. I'm stumped.
Holy Headslap, Batman.
So here's the issue. I'm storing sessions in the database. Somewhere, somehow, an (obviously) automated process changed the cake_sessions.data field to cake_sessions.DATA. Although I've looked at the database a thousand times while debugging this, I just noticed that difference.
Problem solved.
Moral of the story: Developers, don't let your database field names grow up and change case.
You need to set 'Session' as a component too.
I've created a simple CMS to manage several small websites built on CakePHP. After successfully migrating the plugin from 1.3 to 2.0 I'm running into a problem with the AuthComponent after updating Cake to the latest version 2.1.2.
The classnames of the plugin are all prefixed by the plugin's name to avoid duplicate classnames, as the application shares most of its tables with the plugin. So there are cases when I have a UsersController for the main application and a PluginNameUsersController for my CMS plugin (or a PostsController and a PluginNamePostsController). The plugin models rely on $useTable to find the correct database table (so PluginNamePostsController still uses posts).
Since upgrading to the 2.1.* branch of Cake the AuthComponent has ceased to work as it expects a non-existent pluginname_users table instead of referring to users.
Is it possible to define a custom table for the AuthComponent or is there any other method to get this working? Also, is this behaviour expected?
The component is configured in PluginNameAppController as follows:
public $components = array(
'Session', 'RequestHandler',
'Auth'=> array(
'loginAction' => array(
'controller' => 'pluginname_users',
'action' => 'login',
'plugin' => 'pluginname'
),
'loginRedirect' => array(
'controller' => 'pluginname_posts',
'action' => 'index',
'plugin' => 'pluginname'
),
'authenticate' => array(
'Form' => array(
'userModel' => 'PluginNameUser',
'fields' => array('username', 'password')
)
)
)
);
The AuthComponent is actually unaware of tables and such. By using a custom model, you can define $table on it to work on a different table. So, the first thing is to set up your plugin's model to use the proper table:
class PluginNameUser extends PluginAppModel {
public $table = 'users';
}
Then, tell your authentication methods to use the plugin's model by using the dot syntax.
'authenticate' => array(
'Form' => array(
'userModel' => 'PluginName.PluginNameUser',
'fields' => array('username', 'password')
)
)
Now when FormAuthenticate tries to authenticate, it will try and find the user using that model, which it now knows is in PluginName. It loads the model, which you've set to use the users table, and looks for the user there.
Just for organization sake, I wanted to use a different table for the authentication component to check, but it doesn't quite work. While I can initially state:
$this->Auth->userModel = "CoreUsers" plus set the loginAction to my proper MVC
works to look at that table just to confirm it's there, but the login doesn't work, it only keeps returning an incorrect password. Something happens in the authentication component; I can't tell what makes it fail. When I rename my table to "Users", it works.
The other part is I'd prefer to actually use the column name of 'email' rather than 'username' since that's really what I'm using anyway.
I am just not having luck finding a complete tutorial and reference sets to do both these successfully with CakePHP 2.x. What is the way forward?
References:
Stack Overflow question How do I use a table other than "Users" for CakePHP's AuthComponent?
Stack Overflow question CakePHP - 'AuthComponent' with a different model name (not 'User')
(I had a look for answers, but I never quite got the whole answer.)
Make sure your database table "core_users" and model "CoreUser" exists.
When you setup component you can put login/logout redirect here.
var $components = array(
"Auth" => array(
'loginRedirect' => array('controller' => 'dashboard', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'core_users', 'action' => 'login')
),
"Session");
Now in beforeFilter medhod you can put the following
function beforeFilter(){
$this->Auth->authenticate = array(
AuthComponent::ALL => array('userModel' => 'CoreUser', 'scope' => array("CoreUser.status" => 1), "fields" => array("username" => "email", "password" => "your_password_field"), 'Form', 'Basic'
);
}
Above example you can ignore status, if you need to pass any other info on the login verification u can use that. Now about you can remove 'Basic' if you only need form validation.
I hope this would work .
First, model names are generally singular. Are you sure you didn't mean CoreUser which would look in the core_users table?
Secondly, you can use the email field instead of username by setting the fields key on your auth setup.
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'CoreUser',
'fields' => array('username' => 'email')
)
)
)
);
See the book for more information.