Welcome Guest, Not a member yet? Register   Sign In
Authenticate Controller
#1

[eluser]doehoe[/eluser]
My Apologies for this being in the wrong area of the forum. Did it by mistake and don't know how to move it.

This has been discussed before, here and here, but I thought I would put this to the CodeIgniter community before giving up and just using the methods discussed in the above links. I guess the way the above links do it is cool, but I like my way better because it seems more elegant since there is a logical flow instead of using a redirect (which I prefer to avoid as it always feels like a hack).

I want to have an AuthController which extends Controller and which will be the parent class of all Controllers used in the restricted area of my application. This is the way I thought I'd do it:

Code:
abstract class AuthController extends Controller
    {
        function AuthController()
        {
            parent::Controller();
        }
        

        function _remap($method)
        {
            if ($this->_isLoggedIn())
                $this->$method();
            else
            {
                $this->_displayLogin();
            }
        }
        
        function _isLoggedIn()
        {    
            //... code to check if user logged in or not
        }
        
        function _displayLogin()
        {
            //... code to display login form
        }
    }

The _remap function checks if the user is logged in. If he/she is, then it executes the desired function, otherwise it displays a login form. This feels like the neatest way to do it, because any secure controllers in the application just have to extend AuthController instead of Controller without having to do anything else to cater for this new class - i.e. the CodeIgniter controllers would still look like CodeIgniter controllers.

Being a CodeIgniter newbie I didn't spot the problem until I actually tried using the AuthController class and tried to have a controller with functions that took parameters. It seems that I hadn't catered for parameters at all. So now I need to cater for parameters.

The solution I'm looking for should cater for the following:
1) I don't want to have to write a switch statement into the _remap() function which would have a case statement for each function in the controller and use $this->uri->segment() to pass the parameters into relevant function. This is because then each time I add in a new function I would have to add to the switch statement - which would sort of beat the purpose of CodeIgniter's design.

2) I know that PHP caters for a variable number of parameters using the func_get_args() function. So is there a way of passing in the parameters into the $this->$method() from my code above? I don't want to pass the parameters in as an array, I want to pass them in as individual parameters - so that every function in the controller doesn't have to take an array as a parameter as is shown in this solution which I do not like: http://ellislab.com/forums/viewthread/68596/.

I would have tried to search more on the CodeIgniter forums for a solution to this, but it seems that the forum's search is broken, so I had to rely on Google.

Thanks
#2

[eluser]doehoe[/eluser]
Well, I guess I'm going to answer my own question cause I found a nice and (what I believe) elegant solution:

In my above code, replace
Code:
$this->method();

with this:

Code:
call_user_func_array(array($this,$method),array_slice($this->uri->rsegment_array(),2));

What do you think? Is this a good solution?
#3

[eluser]Pascal Kriete[/eluser]
I think you don't need _remap. When a class is instantiated the first thing that always runs is the constructor. Use that to do your check:
Code:
function AuthController()
{
    parent::Controller();
    $this->check();
}
        

function check()
{
    if ( ! $this->_isLoggedIn())
    {
         redirect('login');
        //$this->_displayLogin();
    }
}

// ...

That will let your app run normally unless they're not logged in, in which case the redirect will be called.

I changed it to redirect, because I think it will reduce code fragmentation. Having a dedicated login controller makes handling the login easier as well. You can of course, use _displayLogin if you choose to. Just remember to call exit; or die; so it doesn't show the actual page.
#4

[eluser]Randy Casburn[/eluser]
@inparo - did you miss this part...

Quote:I guess the way the above links do it is cool, but I like my way better because it seems more elegant since there is a logical flow instead of using a redirect (which I prefer to avoid as it always feels like a hack).

...thinks redirect 'feels' like a hack

Randy
#5

[eluser]Pascal Kriete[/eluser]
Thanks Randy,
I totally skipped that intro paragraph :red: .

@doehoe, here are a few more reasons why I think a redirect is the right way to go:
1. Search engines will punish you for duplicate content on all those protected pages (all they see is the login form).
2. As a user, having a dedicated url to login feels more familiar and intuitive. Unless there is a form on the homepage.
3. Every controller will need to lug that login validation and database logic around even when it isn't used.

It still comes down to personal preference, so I rest my case.

Please let us know if the code I posted above works for you (regardless of how you display the form Smile ).
#6

[eluser]doehoe[/eluser]
Quote:@doehoe, here are a few more reasons why I think a redirect is the right way to go:
1. Search engines will punish you for duplicate content on all those protected pages (all they see is the login form).
2. As a user, having a dedicated url to login feels more familiar and intuitive. Unless there is a form on the homepage.
3. Every controller will need to lug that login validation and database logic around even when it isn't used.

Inparo, I know you said you rest your case, but I hope you don't mind if I dissect your reasoning. It is completely friendly and only out of a desire to learn and I'm really not trying to prove I'm right.

I'll just comment on each of your points

1) Shouldn't search engines only see login forms when they try access a secure area? I think they should, in fact I think everybody should be presented with only a login form when they try access a secure area.
2) I agree, but if they get to this login form at a different URL why would they worry? It is also intuitive that they try to access a secure area of the site and be presented with a login form at that secure URL.
3) Your solution also has the "validation and database logic". You can't not have it irrespective of solution.

There is a negative in each case. In my case the controller has to execute that call_user_func_array(array($this,$method),array_slice($this->uri->rsegment_array(),2))
everytime once the user is logged in. In your case the user has to go through a redirect and a new HTTP setup everytime she is not logged in.

It definitely seems like a preference thing ;-)
#7

[eluser]Pascal Kriete[/eluser]
My solution works even if you choose not to use a redirect. As long as you terminate the program once the form is displayed.
Code:
if ( ! $this->_isLoggedIn())
{
    $this->_displayLogin();
    exit;
}

Definitely cleaner than your call_user_func_array magic Wink .

And my rebuttal - for the fun of it:
1. Search engines will index any back-link they find. Particularly (support) forums often point to restricted areas (i.e. "go here, then here, and click there").
2. Yes, they should see a form when they try to access a secure area - and they do - via a redirect.
3. My solution has it in a separate file. If you're using the MY_Controller method, PHP will have to load and parse it on every request. If you're using an include for the secure controllers, it has to load them when you're logged in. In my solution they're only loaded if you're logging in page.

And yes, my argument for 3 deals with rather insignificant numbers - particularly if you're using an opcode cache.
#8

[eluser]doehoe[/eluser]
[quote author="doehoe" date="1225346282"]Well, I guess I'm going to answer my own question cause I found a nice and (what I believe) elegant solution:

In my above code, replace
Code:
$this->method();

with this:

Code:
call_user_func_array(array($this,$method),array_slice($this->uri->rsegment_array(),2));

What do you think? Is this a good solution?[/quote]

Just bringing this topic up again because I found a mistake in my above code which prevents controllers inheriting from AuthController not be able to load libraries/helpers etc. The code should be (noting the &$this):
Code:
call_user_func_array(array(&$this,$method),array_slice($this->uri->rsegment_array(),2));




Theme © iAndrew 2016 - Forum software by © MyBB