I want to apply access roles to the different actions like GET action can be performed by all the users and POST or PUT action can be performed by only logged in users. I don't know how to apply different roles to different actions.
In the mentioned scenario, i would do something like this using session Authorization.
FOR PUT AND POST ACTIONS
public function postAction/putAction
{
if (Zend_Auth::getInstance()->hasIdentity()) {
//YOUR CODE
}
}
FOR GET ACTION
public function postAction/putAction
{
//YOUR CODE
}
This will ensure only logged in users can perform the post and put actions and all will be able to perform the get action.
Related
I have created a CakePHP app where I have created a UsersController, which handles all about users.
When I try to browse www.mydomain.com, if I am logged in, it let's me see the index (app/View/Pages/home.ctp). Else, it redirects me to mydomain.com/users/login and persists to log in.
I have tried looking at AppController.php, PagesController.php or app/Config/core.php and app/Config/routes.php, but did not find anything. My UsersController.php, also, is not responsible for that, I think.
I do not remember and I cannot find how to disable this. Which file should be responsible for that?
EDIT:my CakePHP version is 2.3.
Generally you can make specific actions public using the auth components allow() method.
Making pages public may require a little more work in case you'd want to make only specific pages public, since the PagesController handles all pages in a single action (display()). If that is the case, then you could utilize request->params['pass'][0] which will hold the page name, test this against a list of allowed pages, and then allow the display action using Auth::allow.
Example, in the PagesController:
public function beforeFilter()
{
parent::beforeFilter();
$allowedPages = array('home', 'foo', 'bar');
if(isset($this->request->params['pass'][0]) &&
in_array($this->request->params['pass'][0], $allowedPages))
{
$this->Auth->allow('display');
}
}
This would allow the pages home, foo and bar to be viewed without being logged in.
If you'd wanted to make all pages public, then you could simply use Auth::allow without any conditions, ie:
public function beforeFilter()
{
parent::beforeFilter();
$this->Auth->allow('display');
}
I have a controller in a CakePHP application in which I have a bunch of actions. I'm using the ACL Component to manage which user is allowed to execute which actions in my controller. I have an isAuthorized() action in my controller to check if a certain logged user is allowed to execute a requested action that looks like this:
function isAuthorized()
{
switch($this->action)
{
case 'myAction':
$user_id = $this->Auth->user('id'); // the id of the connected user
if($user_id)
{
return $this->Acl->check(
array('model' => 'MyModel', 'foreign_key' => $user_id),
'controllers/MyController/myAction'
);
}
break;
}
}
As you can see above, all I'm doing is check if the connected user is allowed to execute myAction by using the method check of the Acl component. The problem I have with this approach is that this check is done every single time myAction is called. Is there a way to tell Cake to perform this check only one time (on the first call of the action for example)?. By checking every single time if a user is allowed to execute a controller action that slows down the application a lot.
Any help or suggestions is appreciated
Thank you
Technically speaking, HTTP is stateless and each request does not have any affinity to any other request from the same user. State-fullness is created by using sessions.
You could store the ACL check result in a session variable. But you would need some way to reset it if the users access were to change while logged in.
i have built upon this tutorial http://www.jamesfairhurst.co.uk/posts/view/creating_an_admin_section_with_cakephp_updated
and currently have a functional and quite well fleshed out admin section for my application.
Due to poor foresight I haven't taken into account regular users who need to be able to login to their own home page, where they can view bookings etc.
I have an appropriate database set up and have included a 'roles' field for authentication. I have also followed cakePHP's own 'auth' examples however have failed to get them to implement without throwing various errors, at this stage i'm not wanting to go changing the structure of the login system too much, that kind of thing can become a headache quick!!
I have spoken to the original author of the tutorial and he agrees that some simple logic added to the user_controller.php file should suffice.
basically i need something along the lines of an: "if user == 'user' THEN redirect to 'user_index.php' put simply.
below is the current LOGIN function for user_controller.php
function login() {
if(!empty($this->data)) {
// unset unrequired validation rules
unset($this->User->validate['username']['check_username_exists']);
// validate form
$this->User->set($this->data);
if($this->User->validates()) {
// update Last Login date
$this->User->id = $this->User->_user['User']['id'];
$this->User->saveField('last_login',date("Y-m-d H:i:s"));
// save User to Session and redirect
$this->Session->write('User', $this->User->_user);
$this->Session->setFlash('You have successfully logged in.','default',array('class'=>'flash_good'));
$this->redirect(array('action'=>'index','admin'=>TRUE));
}
}
}
All validation is handled in the user.php model and there is some logic in app_controller.php to redirect authentication, it is included below;
app_controller.php
class AppController extends Controller {
// class variables
var $_User = array();
/**
* Before any Controller action
*/
function beforeFilter() {
// if admin url requested
if(isset($this->params['admin']) && $this->params['admin']) {
// check user is logged in
if( !$this->Session->check('User') ) {
$this->Session->setFlash('You must be logged in for that action.','flash_bad');
$this->redirect('/login');
}
// save user data
$this->_User = $this->Session->read('User');
$this->set('user',$this->_User);
// change layout
$this->layout = 'admin';
}
}
}
I faced a similar problem in my application. In my User model, I created a getRole() method which just pulled the role out of the database, and then I used a switch statement to redirect users to the correct controller.
As a different approach, you could just add in an isAdmin column (default 0, 1 would indicate an admin) to your users table. Assuming there are not too many admins already, you could just manually set the admins. In your controller you would just need to check the field and the redirect accordingly.
I am in the process of building a webapp in cakePHP where once a user has signed up they would have their own profile page that can be seen by other members. Ideally I would like a nice url e.g. www.website.com/davejones but I can settle for something that was like www.website.com/uid=235325.
What would be the best way of going about this?
Basically you would just add a profile method to your UsersController that takes the user id/username as a parameter and then just serve that page.
class UsersController extends AppController {
public function profile($uid) {
$data = $this->User->findById($uid);
$this->set(compact('data'));
}
}
Would make all data of that user (incl. associated data, if your models setup properly) go into the $data variable that you can call from your view. Do with it what you want there.
In CakePHP we can use $this->Auth->allow('someMethod'); to make a page viewable without having to login. How do I make some the same page is not viewable when a user is logged in? An example of this would be a register page which we want to be accessible without user logged in ... but not accessible once a user logged in.
I put $this->Auth->deny('someMethod') in isAuthorized() but it seems to me that if the method is in the allow list then isAuthorized is not called when we try to run that page.
Any input? Thank you
There are no complex rules like that built into Cake Auth. You'll have to manually check for conditions like this. It's very simple though:
// Controller
function register() {
if ($this->Auth->user()) {
$this->redirect(/* somewhere else */);
}
}
Contrary to mlevits answer, you don't need to store anything in the Session, the info is readily available from the AuthComponent itself. http://book.cakephp.org/view/387/user
There's also an example how to do it by dynamically using deny(), but that's not as clear in a simple case like this IMHO. http://book.cakephp.org/view/383/deny
Also, deny() produces an error message ("You're not authorized to access this location"), which is probably not what you want for the user experience in this case.
EDIT:
Wasn't aware that CakePHP used a different syntax.
You can then use the following to set the Session variable:
$this->Session->write('user_id', '<some_user_name>');
Then use this to redirect the user if they are logged in:
if ($this->Session->check('user_id'))
{
$this->redirect('http://google.com');
}
And then to destroy a Session use:
$this->Session->destroy()
More information about CakePHP Sessions
Thanks
You can check it in method beforeFilter in AppController to allow aplication-wide check. For example:
<?php
class AppContoller extends Controller {
var $components = array('Session', 'Auth');
function beforeFilter(){
$this->Auth->allow('register', 'home');
// Check if current action allowed to access without authorization and User has login
if(array_key_exists($this->params['action'], $this->Auth->allowedActions) && $this->Auth->user()){
$this->redirect(/* somewhere else */);
}
}
}
?>
Of course you can also implements it in some controller instead of AppController.