Deny admin routes for specific and not logged users - cakephp

I have two groups id :
Group 1 => Admins
Group 2 => Users
I'm looking for a way to deny the access for the users which are not admin (so group 2 and not logged) . The function isAuthorized doesn't work, i mean it's always return true, i just don't know why . Thanks for your help
<?php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
public $helpers = array('Html', 'Form', 'Session');
public function beforeFilter() {
parent::beforeFilter();
//Configure AuthComponent
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'pages', 'action' => 'home');
if(isset($this->request->params["prefix"]) && $this->request->params["prefix"] == "admin"){
$this->layout = "admin";
} else {
$this->layout = "default";
}
}
public function isAuthorized() {
parent::isAuthorized();
if(isset($this->request->params["prefix"]) && $this->request->params["prefix"] == "admin" && $this->Auth->user('group_id') === 1){
return true;
}
else {
return false;
}
}
}
PagesController
<?php
class PagesController extends AppController {
/**
* This controller does not use a model
*
* #var array
*/
public $uses = array();
/**
* Displays a view
*
* #param mixed What page to display
* #return void
* #throws NotFoundException When the view file could not be found
* or MissingViewException in debug mode.
*/
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow();
}
public function display() {
$path = func_get_args();
$count = count($path);
if (!$count) {
return $this->redirect('/');
}
$page = $subpage = $title_for_layout = null;
if (!empty($path[0])) {
$page = $path[0];
}
if (!empty($path[1])) {
$subpage = $path[1];
}
if (!empty($path[$count - 1])) {
$title_for_layout = Inflector::humanize($path[$count - 1]);
}
$this->set(compact('page', 'subpage', 'title_for_layout'));
try {
$this->render(implode('/', $path));
} catch (MissingViewException $e) {
if (Configure::read('debug')) {
throw $e;
}
throw new NotFoundException();
}
}
public function admin_index() {
$title_for_layout = 'Dashboard';
$this->set(compact('title_for_layout'));
}
}
routes
*/
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home'));
/**
* ...and connect the rest of 'Pages' controller's urls.
*/
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/admin', array('controller' => 'pages', 'action' => 'index', 'admin' => true));

To auto add prefix from action like admin_ you need to add the following line in your core.php file:
Configure::write('Routing.prefixes', array('admin'));
Then, the action PagesController::admin_index is accessible by /admin/pages/index instead of /pages/admin_index and the admin param is set to true so you can check it using $this->params['admin'] (see my code bellow).
Actually, in CakePHP all routes are denied by default but you allow all routes in PagesController by doing $this->Auth->allow() in the beforeFilter, you need to add an exception for admin.
To do so, in your AppController:
<?php
class AppController {
public $components = array(
'Auth' => array(
'loginAction' => array('controller' => 'users', 'action' => 'login');
'loginRedirect' => array('controller' => 'pages', 'action' => 'home');
'logoutRedirect' => array('controller' => 'users', 'action' => 'login');
'authorize' => array('Controller'),
)
) ;
public beforeFilter() {
parent::beforeFilter() ;
// Allow everything to not logged user except admin pages
if (isset($this->params["admin"])
&& $this->params["admin"]) {
$this->Auth->deny() ;
}
else {
$this->Auth->allow() ;
}
}
public isAuthorized() {
if (isset($this->params["admin"])
&& $this->params["admin"]) {
return $this->Auth->user('group_id') === 1 ;
}
return parent::isAuthorized() ;
}
} ;

Related

Display username after login in cakephp3

I want to display username after login in cakephp3. I write follow code but part of show username doesn't work. user after login redirect to main page.
Hi <?php print $this->request->session()->read('User',$user); ?>
login in UserController:
public function login() {
if ($this->request->session()->read('login_ok') == '1') {
$this->redirect(['controller' => 'users', 'action' => 'main']);
}
if ($this->request->is('post')) {
//$hasher = new DefaultPasswordHasher();
$count = $this->Users->find()
->where(['username' => $this->request->data['username'],
// 'password' => $this->request->data['password']])
'password' => md5($this->request->data['password'])])
->count();
if ($count > 0) {
$result = true;
$this->request->session()->write('User', $user); //store username
$this->request->session()->write('login_ok', '1');
$this->redirect(['controller' => 'users', 'action' => 'main']);
} else {
$result = false;
}
$this->set('result', $result);
}
}
public function main() {
if ($this->request->session()->read('login_ok') != '1') {
$this->redirect(['controller' => 'users', 'action' => 'login']);
}
$query = $this->request->session()->write('User',$user);
$this->set('user', $query);
}
and this main.ctp codes:
Hi <?php print $this->request->session()->read('User', $user); ?>
Can you help in making this Code OR Suggest a new code ?
You should really be using the cakephp AuthComponent and the functions that's made for this for example identifiying the user trying to login with identify().
There is really no point using a framework if you're not going to use the functions provided by the framework as N Nem pointed out in the comments.
In the snippet you posted, you seem to never set the $user variable when you write to the session. You need to set it to be able to read it.
The following code is how you're supposed to do it in Cakephp 3 i really suggest you use that approach.
AppController.php
public function initialize()
{
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
],
'loginRedirect' => [
'controller' => 'Start',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login'
],
'authenticate' => [
'Form'
],
]);
}
UsersController.php
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error(__('Username or password is incorrect'), [
'key' => 'auth'
]);
}
}
}
Model/Entity/User.php
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}

Cakephp 2 Auth Redirect Loop

CakePhp 2 redirect loop on Web Hosting. But it working on local computer. Has anyone can solve my problem?
This is my AppController
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
),
'authenticate' => array(
'Form' => array(
'scope' => array('User.status' => '1')
),
),
),
'Session',
'DebugKit.Toolbar',
);
public $helpers = array('Html', 'Form', 'Session');
public $uses = array(
'Configuration.Configuration',
'EmailTemplate.EmailTemplate',
);
public $theme = "";
public function beforeFilter() {
//Configure AuthComponent
$this->Configuration->load();
$this->Auth->loginAction = array(
'controller' => 'users',
'action' => 'login',
'plugin' => false
);
$this->Auth->logoutRedirect = array(
'controller' => 'users',
'action' => 'login',
'plugin' => false
);
$this->Auth->loginRedirect = array(
'controller' => 'users',
'action' => 'dashboard',
'plugin' => false
);
$this->check_group();
####### Define Plugin layout #######
if($this->params['plugin']=='content')
$this->layout = 'content';
}
private function check_group()
{
$this->theme = 'CakeReady';
if (isset($this->request->params['admin'])) {
$this->layout = 'admin';
}
if ($this->params['plugin'] == 'acl') {
$this->layout = 'acl';
}
if ($this->request->is('ajax')) {
$this->layout = 'ajax';
}
if(!isset($this->request->params['admin']) && Configure::read('Site.coming_soon') == 1){
$this->theme = 'CakeReady';
$this->layout = 'coming_soon';
$this->set('title_for_layout', __('Coming Soon'));
}
else if (!isset($this->request->params['admin']) && Configure::read('Site.status') == 0){
$this->theme = 'CakeReady';
$this->layout = 'maintenance';
$this->set('title_for_layout', __('Site down for maintenance'));
}
else if (!isset($this->request->params['admin'])){
$this->theme = 'CakeReady';
$this->layout = 'coming_soon';
$this->set('title_for_layout', __('Coming Soon'));
}
}
And its my UsersController
class UsersController extends AppController {
/**
* Components
*
* #var array
*/
public $components = array('Paginator','Qimage');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('admin_forget_password', 'login', 'admin_login','subscriber','activate_code', 'register', 'captcha');
}
public function login() {
$show_action = 'login';
$this->layout = 'admin_login';
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->Session->setFlash(__('Congratulation You are login succcessfully.'), 'success');
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash(__('<h4>Your username or password was incorrect.</h4>'), 'errorText');
}
$this->set(compact('show_action'));
}
/**
* admin_login method
*
* #return void
*/
public function admin_login() {
$show_action = 'login';
$this->layout = 'admin_login';
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->Session->setFlash(__('Congratulation You are login succcessfully.'), 'success');
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash(__('<h4>Your username or password was incorrect.</h4>'), 'errorText');
}
$this->set(compact('show_action'));
}
is mod_rewrite enabled?
You have this too?
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ webroot/ [L]
RewriteRule (.*) webroot/$1 [L]
</IfModule>

How can i change the default route when the user is logged?

In my config.php file, this is the default router.
Router::connect('/', array('controller' => 'users', 'action' => 'signup'));
If users are not connected, they do not have the right to access to the edit actions and view action in the UsersController .
<?php
class UsersController extends AppController{
public $uses = array('User', 'Company', 'Town');
public function beforeFilter(){
parent::beforeFilter();
// If the user is not connected he can't access to these pages
$this->Auth->deny('view', 'edit');
}
}
When users use the login form and are logged in, they are redirected to the page controller and index action.
I would like that they can not enter (user and admin role) to the action signup of the controller Users.
Therefore changed the default route when the user is connected (either admin or user) . But i don't know in my case what i should do .
AppController :
<?php
class AppController extends Controller{
public $helpers = array('Text','Form','Html','Session','Cache');
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'pages', 'action' => 'index'),
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email')
)
)
)
);
function beforeFilter(){
$this->Auth->loginAction = array('controller'=>'users','action'=>'login','admin'=>false);
//tell Auth to call the isAuthorized function before allowing access
$this->Auth->authorize = array('Controller');
//allow all non-logged in users access to items without a prefix
if(!isset($this->request->params['prefix'])){
$this->Auth->allow();
}
if(isset($this->request->params['prefix']) && $this->request->params['prefix'] == 'admin'){
$this->layout = 'admin';
}
// Si l'utilisateur est connecté
if (isset($this->Auth) && $this->Auth->user('id')) {
$this->layout = 'user';
}
}
function isAuthorized($user){
if(!isset($this->request->params['prefix'])){
return true;
}
$roles = array(
'admin' => 10,
'user' => 5
);
return false;
}
}
Thanks .
I found a way to do what I wanted without using ACLs but I do not know if this is the best solution and if it is safe, what do you think?
In Appcontroller in the action beforefilter ()
$role = $this->Auth->user('role');
if ($role == 'user' || $role == 'admin' && $this->request->params['controller'] == 'users' && $this->request->params['action'] == 'signup') {
$this->redirect(array('controller' => 'pages', 'action' => 'index'));
}

Restricting and redirecting other user from admin in cakePHP

I'm getting issue after logging in the site. There are two kinds of users i.e. 'admin','employer'. When I've logged in by employer, I can access the restricted area of Admin. Below is the AppController of the site..
class AppController extends Controller {
public $helpers = array('Form', 'Html', 'Js', 'Time', 'Auth');
// Change template extension to .php instead of .ctp
var $ext = '.php';
public $components = array(
'Session',
'Auth' => array(
'loginAction' => array(
'controller' => 'users',
'action' => 'login'
),
'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'authenticate' => array('Form' => array('fields' => array('username' => 'email'))),
'authorize' => array('Controller')
)
);
public function isAuthorized($user) {
// Admin can access every action
if (isset($user['type']) && $user['type'] === 'admin') {
return true;
}
// Default deny
return false;
}
public function beforeFilter() {
$this->Auth->allow(array('view', 'index','assessment','question'));
}
}
Now here is the controller which has methods for admin.
class TopicsController extends AppController {
public $scaffold = 'admin';
public function beforeFilter() {
if($this->Auth->user('type')!='employer'){
parent::beforeFilter();
$this->Auth->allow(array('view', 'index','moveup'));
} else {
$this->Auth->deny(array('view', 'index','moveup'));
$this->redirect(array('controller' => 'employer' , 'action' => 'index'));
}
}
public function isAuthorized($user) {
return true;
}
public function index() {
$this->set('topics', $this->Topic->children());
}
}
If admin URL is www.example.com/admin/topics , Employer is redirected to www.example.com/admin/employer which is not right URL to be redirected.
Also want to know about public $scaffold = 'admin'; as It's little unclear to me.
Please help me..
Ok.. Found one way to redirect, which made my issue solved for a now.. Still looking for proper answer if anybody has..
I changed code from
$this->redirect(array('controller' => 'employer' , 'action' => 'index'));
to
$this->redirect('employer');
..
EDIT: Thanks Alex, I've used
$this->redirect(array('controller' => 'employer' , 'action' => 'index', 'admin'=>false));
and it's working too..

Checking user role on login using CakePHP?

I want to create an admin panel for my site, for this I've created admin.ctp. In DB table name user contain column role, where role=admin/regular(user).
There is only one login form, and the question is, Is it possible to place a 'check' that if user.role=admin then redirect to the admin/user/dashboard and if user.role=regular then layout=default? my AppController.php contains:
function beforeFilter(){
$this->Auth->allow('index','view','login','home');
$this->set('admin',$this->_isAdmin());
$this->set('logged_in',$this->Auth->loggedIn());
$this->set('current_user',$this->Auth->User());
if ((isset($this->params['prefix']) && ($this->params['prefix'] == 'admin'))) {
$this->layout = 'admin';
}
And usersController.php
function beforeFilter(){
parent::beforeFilter();
$this->Auth->allow('*');
if($this->action=='add' || $this->action=='edit'){
$this->Auth->authenticate=$this->User;
}
}
function login(){
if(!($this->Auth->loggedIn())){
if ($this->request->is('post')) {
if ($this->Auth->login()) {
if($user['role'] === 'admin'){
$this->redirect($this->Auth->redirect('admin',array('controller' => 'user','action' => 'admin_dashboard')));
}
$this->redirect($this->Auth->redirect(array('controller' => 'posts','action' => 'index')));
} else {
$this->Session->setFlash('Your username/password combination was incorrect.',
'alert',array(
'plugin' => 'TwitterBootstrap',
'class' => 'alert-error'
));
$this->set('forget', 'Forgot Your Password');
}
}
}else
{
$this->redirect($this->Auth->redirect(array('controller' => 'posts','action' => 'index')));
}
}
using cakephp 2.2.3.
thanks in advance!
This is how I would do it (remember to change field('name') accordingly with your group model).
if ($this->Auth->login())
{
this->User->Group->id = $this->Auth->user('group_id');
switch ($this->User->Group->field('name'))
{
case 'admin':
$this->redirect($this->Auth->redirect('admin',array('controller' => 'user','action' => 'admin_dashboard')));
break;
case 'regular':
$this->redirect($this->Auth->redirect(array('controller' => 'posts','action' => 'index')));
break;
default:
//...
break;
}
}
In AppController set:
$this->Auth->authorize = array('Controller');
And then do the following
public function isAuthorized($user = null)
{
if (isset($this->request->params['admin']))
{
if(!isAdmin)
{
return false;
}
}
return true;
}
CakePHP actually already provides a useful Authentication and Authorization framework that's trivial to enable.
Here's how to authorize based on a role stored in the database, from the CakePHP manual. I also included an example beforeFilter() that changes the login redirect action if the user is an admin:
AppController.php:
public $components = array(
'Auth' => array(
'authorize' => array('Controller'),
'loginRedirect' => array('/'),
));
public function beforeFilter() {
// This allows us to use $user in all controllers.
$this->set('user', $this->Auth->user());
// If the user is an admin, override the loginRedirect
if ('admin' === $this->Auth->user('role')) {
$this->Auth->loginRedirect = array(
'controller' => 'users',
'action' => 'admin_dashboard',
));
}
}
UsersController.php:
public function isAuthorized($user) {
// Ensure the user has a valid role. If not, deny access to all actions:
if ((!isset($user['role'])) || ('' === $user['role'])) return false;
// If we're trying to access the admin view, verify permission:
if ('admin_dashboard' === $this->action)
{
if ('admin' === $user['role']) return true; // User is admin, allow
return false; // User isn't admin, deny
}
return true;
}
There are many ways you can arrange the authorization, so adjust the if/else statements to best suit your needs. The isAuthorized() method is relatively simple, you just need to return true if you want to allow access, or false if you don't.
I actually want to post some code to perhaps shed light on this subject for myself as well.
I have achieved a simple dashboard for each user that extends the /Users/view - my next step is trying to get User-specific access to each set of data
AppController
class AppController extends Controller {
public $components = array(
'Acl',
'Auth' => array(
'authorize' => array(
'Actions' => array('actionPath' => 'controllers')
)
),
'Session'
);
public $helpers = array('Html', 'Form', 'Session');
public function beforeFilter() {
//Configure AuthComponent
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->logoutRedirect = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'dashboard');
$this->Auth->allow('display');
}
}
UsersController
public function dashboard() {
$id = $this->Auth->user('id');
$this->set('user', $this->User->read(null, $id));
$group_name = $this->User->Group->field('name', array('id' => $this->Auth->User('group_id')));
$this->redirect = array('controller' => 'users', 'action' => 'dashboard');
}
dashboard.ctp
$this->extend('/Users/view');
<?php public function dashboard() {
$id = $this->Auth->user('id');
$this->set('user', $this->User->read(null, $id));
$group_name = $this->User->Group->field(
'name', array('id' => $this->Auth->User('group_id'))
);
$this->redirect = array('controller' => 'users', 'action' => 'dashboard');
}
?>

Resources