for my client's website I have an admin section- only thing is my admin routing doesn't seem to be password protected. I added the admin protection with a tutorial on how to set up a user system, and have placed the following code in app_controller.php:
function beforeFilter() {
// if an admin route is requested and not logged in
$user = $this->Session->read('User');
if(isset($this->params['admin']) && $this->params['admin'] && is_null($user)) {
// set Flash and redirect to login page
$this->Session->setFlash('You need to be logged in for that action.','default',array('class'=>'flash_bad'));
$this->redirect(array('controller'=>'users','action'=>'login','admin'=>FALSE));
}
}
& in my app/config/routes.php I have this:
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Router::connect('/admin/logout', array('controller' => 'users', 'action' => 'logout'));
which I'm pretty sure is missing something for the protection.
I can still access other admin areas without logging in though, i.e. theowlhouse.com.au/admin/bookings.
What am I doing wrong? The admin page for the users model is the only protected one.
Thanks :)
It looks like you're confusing prefix routing with using the auth component. Note that prefix routing was called 'admin routing' prior to version 1.3.
You don't need to use admin routing to use the auth component. Let's start with just getting the auth component set up. In your app controller, make sure you have it included in your components array:
var $components = array('Auth');
Once you've done that, users will be directed to a login page unless they are logged in. To allow anonymous users to access an action, you make a called to $this->Auth->allow('action name'); So, for example, say you want to allow unauthenticated users to use the index() and view() actions in your items controller, but not add() or edit(). In your items_controller.php, you would set up the beforeFilter() to make a call:
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow(array(
'index',
'view'
));
}
Related
Is there way to set different logout routes based on the prefix?
I have Admin, Members as two prefixes, when the session is timed out both of them are redirected to the same login page, I want to set different login pages for each of the prefixes.
Sure is, just check existing url's prefix and update login url accordingly.
In your AppController::beforeFilter() you can do:
$loginAction = ['controller' => 'users', 'action' => 'login'];
if (!empty($this->request->params['prefix'])) {
$loginAction[$this->request->params['prefix']] = true;
}
$this->Auth->loginAction = loginAction;
my UserController.php has logout function that looks like this
function logout()
{
$this->Session->destroy('User');
$this->Session->setFlash('You\'ve successfully logged out.');
var_export($this->Session->read('User'));
//$this->redirect('login');
}
my view Users/index.ctp
<?php echo $this->Html->link('Logout', array('controller' => 'users', 'action' => 'logout')); ?>
When I click "log out" the var_export still displays all the User data and if I go back to Users/index.ctp it still shows me that page even though in my my UserController.php I am checking if User is set
function beforeFilter()
{
$this->__validateLoginStatus();
}
function __validateLoginStatus()
{
if($this->action != 'login' && $this->action != 'logout')
{
if($this->Session->check('User') == false)
{
$this->redirect('login');
}
}
It does not redirect to login page and just brings me to index page.
}
$this->Session->destroy();
The destroy method will delete the session cookie and all session data stored in the temporary file system.
User to remove, use better delete.
$this->Session->delete('User');
If you use the AuthComponent to authenticate the users, you can log them out by using the logout() method.
$this->Auth->logout();
See http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#logging-users-out for Cake 2 or http://book.cakephp.org/1.3/en/view/1262/logout for Cake 1.3
And if you don't use the AuthComponent at all, you should maybe have a look at it as it contains out of the box many functionalities that you have already or will likely implement yourself.
I want to have a login form in my home page, the registered users should be redirected to users/index
with the below code, my home page is going to redirect loop
can anyone tell me where is the issue ??
Note:- infact it is perfectly working if i change the line to
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
App Controller
public function beforeFilter(){
$this->Auth->autoRedirect = false;
$this->Auth->loginAction = array('controller' => './', 'action' => 'index');
$this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller' => './', 'action' => './');
$this->Auth->authorize = 'controller';
$this->Auth->authError= 'You need permissions to access this page';
$this->Auth->allow('index');
$this->set('Auth',$this->Auth);
}
UsersController
public function login(){
$id = $this->Auth->user('id');
if(empty($id)){
if($this->request->is('post')){
if($this->Auth->login()){
$this->redirect($this->Auth->redirect());
}else{
$this->Session->setFlash('Invalid Username or password');
}
}
}else{
$this->redirect(array('action'=>'index'));
}
}
Thanks for the help...
You pretty much answered your own question here:
Note:- infact it is perfectly working if i change the line to
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
Indeed that would work and that is what it should look like. Right now, you're telling the auth component your loginAction (the action which holds your login logic) is the index action of the ./ controller (which doesn't even exist). I'm assuming you're confusing it with the loginRedirect variable, which is for setting the page to go to after successful authentication.
If you only want Registered Users to Access Your Site you could have something like this... at least, this is how I implement something similar in my site...
In your app_controller file add the following to the beginning of your beforeFilter() function
function beforeFilter(){
//Check if user was able to log in thru Auth using your form in the homepage
if($this->isLoggedIn() == TRUE){
$this->layout = 'default'
}else{
// You can created this layout with a login form and
// whatever else you need except <?php echo $content_for_layout; ?>
// Any registered user will be allowed to login using the form
// and continue on to your site using the default layout
// But it guarantees no one else can see your default site
$this->layout = "unregistered_user"
}
}
On your App_controller.php you can create this function
function isLoggedIn(){
// You can also use $this->Auth->user directly in your App's beforeFilter()
// But I just like to have functions so I can reuse
if($this->Auth->user()){
$loggedin= TRUE;
}else{
$loggedin= FALSE;
}
return $loggedin;
}
I have something similar of my site but is only used when in maintenance mode. I am still developing my site. The only problem I've seen with this way, which I have not yet have time/need to look at, is that my errors are not sent to the layout I want. Supposed a user types in http://www.mydomain.com/inexistentpage then cake transfers them to my default layout. It might be easy to fix, but I havent got time to do that yet.
NOTE: I quickly did this off the top of my head and because of it, this code is untested. However, if you have any issues please let me know and I will test it and post back.
using $this->requestAction(anotherController/action); in the view might call to another controller->action. you must ensure that the another controller->action has the right permissions. or you'll get redirect loop.
solve it by adding $this->auth->allow('action name'); to the another controller page in the beforeFilter() callback.
I know this must be something really stupid, but I am having issues with logging out. I can still see the full user Auth variable after calling Auth->logout(). In my users controller I have the standard:
function login()
{
}
function logout()
{
$this->redirect($this->Auth->logout());
}
But when I call logout, in my view I can still print the User by doing this:
$auth = $this->Session->read('Auth.User');
print "<pre>";
print_r($auth);
print "</pre>";
Am I missing something basic here? Thanks!
mine:
function logout() {
$this->Session->destroy();
$this->redirect($this->Auth->logout());
}
you have not allowed the use of the logout function, and the user is redirected instead of logged out.
in your controller containing logout the function, add this in your before filter:
$this->Auth->allow('logout');
In your app controller you must define a loginAction, in case of a not authorized entry, the view is redirected to that URL
'Auth' => array(
'loginRedirect' => array('controller' => 'products', 'action' => 'all'),
'logoutRedirect' => array('controller' => 'products', 'action' => 'index'),
'loginAction' => array('controller'=>'admins', 'action'=>'login'),
)
You'll find that if you just create a beforeFilter() function in UserController with that one line, you'll break the authorization on the Users model. That is, any user will be able to do users/add, users/edit, etc. To fix this, make sure you call AppController's beforeFilter. The complete beforeFilter() function looks like this:
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('logout');
}
If CakePHP is using PHP sessions and not rolling their own, you could just clear out the session on logout via session_destroy();. Sorry I have no CakePHP experience, so I'm just going off of an assumption.
what cake version do you have? I think you have to manually clear session in Cake 1.2. In newer Cake, if the logout function is called, it would clear out Auth.User; I'm sure on that.
I can't see a reason why this shoudn't work as I use exactly the same code...
did you confirm that the method is actually called? a simple "die('xyz')" etc before the Auth logout part can confirm that your action code is triggered.
I have an issue with cake's auth that I simply can't seem to get past (i've been debugging and trying different tutorials for the last two days). As far as I can see it should be very simple, the problem is whenever i try to login, it just refreshes the login page. I cannot for the life of me figure out why! My only conclusion is that there must be something (basic) which tutorials take for granted that I have missed.
Here are a couple of snippets:
users_controller.php
class UsersController extends AppController {
var $name = 'Users';
function beforeFiler() {
parent::beforeFilter();
}
function login() {
}
function logout() {
$this->Session->setFlash('You have successfully logged out.');
$this->redirect($this->Auth->logout());
}
}
app_controller.php
class AppController extends Controller {
var $helpers = array('Html','Form','Javascript');
var $components = array('Auth');
function beforeFilter() {
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->loginRedirect = array('controller' => 'contents', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller' => 'contents', 'action' => 'view');
$this->Auth->loginError = 'Something went wrong';
$this->Auth->allow('register', 'view');
$this->Auth->authorize = 'controller';
$this->set('loggedIn', $this->Auth->user('id'));
}
function isAuthorized() {
return true;
}
}
login.ctp
<div class="midCol short">
<h3>Login</h3>
<div class="loginBox">
<?php e($form->create('User', array('controller'=>'users','action'=>'login')));?>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
e($this->Form->end(array('label'=>'Login', 'class'=>'loginButton button png')));?>
</div>
</div>
Any help would be greatly appreciated, this has me tearing my hair out!
Just for documentation as I had difficulties finding an answer for CakePHP 2.x on the web. This stuff needs to be "correct" in order to use Form authentication:
The config needs to be right, e.g. in your UsersController (the fields config is really only required when names differ in the DB):
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array(
'username' => 'username',
'password' => 'password'
),
)
)
)
);
You have to use the Form Helper: Form->create adds a hidden input field ("post"), and the names of the input fields generated by Form->input() follow a convention that the Auth component expects.
User->login must not pass custom data to Auth->login(). The Auth component will take the auth data from the form (= request).
Thanks for the advice, but I ended up scrapping it and building again from scratch. Not exactly sure why it was originally breaking, probably not calling inbuilt functions with American English!
The Auth component will redirect to the page before you logged in. If that page was the login page that's where it'll redirect to.
When you're testing, it's likely that you're refreshing the login page, so on successful login that's where you're redirected to. You can check this by trying to perform an Auth protected action after logging in.
This gives me a lot of headaches as well - I think the current functionality of the component is a little clumsy in that respect.
I had the exact same problem and found that I had to restart mySQL service. Once it was restarted I stopped getting the login page being redirected. Hope that helps.
Gonna throw something in here. I was having an almost unresolveable problem with cakephp authentication. Ended up doing some debugging around it and found that during my database prep I had created a field for the password which was perfectly able to store normal size passwords... but.... when you start applying password hashing you need a lot more. My code was fine, but I had to add a bunch more space into the VARCHAR field for the password before I could log in. If you're having a problem with authentication - make sure your password field is adequately sized and not getting truncated like mine was. Took me a whole day to find that. DOH!
Correct me if i am wrong but must there not be code for redirection or something inside the function of login
function login() {
}
should it not be something like
public function login()
{
if ($this->request->is('post')) {
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid username or password, try again'));
}
}