I have created basic login setup based upon cookie alone in codeigniter.
like this
class Display extends CI_Controller {
public function Display() {
parent::__construct();
}
public function index() {
//var_dump($_COOKIE);
if (isset($_COOKIE["user"])){
redirect('home')
}else{
redirect('display/login');
}
}
public function login() {
//var_dump($_COOKIE);
if (isset($_COOKIE["user"])){
$this->load->view('home');
}else{
$username = $this->input->post('username');
//some validation
setcookie("user",$username,time()+60*60*24*30);
redirect('home');
}
}
}
In the home controller i check for the cookies to access the page
class Home extends CI_Controller {
public function Home() {
parent::__construct();
//var_dump(get_cookie("user"));exit;
if (isset($_COOKIE["user"]) == false){
redirect('display/login');
}
}
}
The problem i am facing here is i cant get cookie in the constructor of the class. i need check for cookie in class before accessing any of the function in the class. what will be the proper way to do it ?. Thanks in advance.
You don't assign the path parameter of the cookie, so it gets the path of the page it's assigning it and results to be /login or something similar and it won't be sent to other parts of your page like /home, or simply the root. Change the setcookie() like to somethig like this:
setcookie("user",$username,time()+60*60*24*30, '/'); // notice the added path at the end
Also anyone can set cookies in their client, relaying only their existence as authentication is not secure at all, anyone can change what their user cookie holds.
You'd probably be better off using CodeIgniter's own implementation (Cookie_Helper): http://ellislab.com/codeigniter/user_guide/helpers/cookie_helper.html
Check out CodeIgniter User Guide Version 2.2.0: Input Class.
Use $this->input->set_cookie() to set cookie and $this->input->cookie() to get cookie
Related
I am working with Codeigniter PHP.
I want if admin not login then he can't see admin panel pages.
For this i created helper.
The Code is working if I put condition is every function but if I use this code in "constructor" then redirect to home page but also showing "login" page after home page.
Where I am wrong ?
Here is my code (using in one of my function which is working )
public function admin_offers(){
if (!is_logged_in()) {
$this->index();
//die();
}
else {
$data['offers']=$this->db->get('offers')->result();
$this->load->view('admin/special-offers',$data);
}
}
And here is my code in constructor, which is not working for me.
public function __construct() {
parent::__construct();
$this->load->model("stores_model");
$this->load->library("pagination");
$this->load->library('encryption');
is_logged_in();
if (!is_logged_in()) {
$this->index();
}
}
First, from your code, you are calling the function twice which is unnecessary.
is_logged_in(); //this calls the function
if (!is_logged_in() /* this too */) {
$this->index();
}
For your case, try this:
function __construct(){
parent::__construct();
$this->load->model("stores_model");
$this->load->library("pagination");
$this->load->library('encryption');
if (!$this->session->user_data('session_name')) {
redirect('controller_name/function'); // the public page
}
}
Basically, what the code does, it checks if the session data(set during login) exists, if it does not exist, the user is redirected to the public page(possibly the login page).
If you place the code under the __construct function, no need to include it in individual functions as this code is executed when the class is instantiated, hence executed before the functions are loaded.
NB: Make sure you have already loaded session library in autoload
What is the most secure way of checking if a user is logged in? I am using php's framework, codeigniter.
$loggedIn = $this->session->userdata('is_logged_in'); // returns 1
if($loggedIn == true): ?>
// do something
<?php endif; ?>
Does it matter if this code is in the controller or in a view?
Well, the view is for the presentation logic and in this case you should keep the code in the controller but if it relates with the view, for example, if you have a navigation and if you show different menu for a logged in user then you can use in your controller
$loggedIn = $this->session->userdata('is_logged_in');
// ....
$data['loggedIn'] = $loggedIn;
$this->load->view('viewname', $data)
and pass the variable to the view from the controller and then in the view you can check
<?php if($loggedIn ): ?>
// Show menu for logged in user
<?php else: ?>
// Show a different menu
<?php endif; ?>
Keep only some loops like foreach to build a menu or populating a dropdown e.t.c and if statements (when needed) in the view.
When you _construct the controller, you could find if they are logged in or not from the get-go. If they aren't, send them to the login screen:
function __construct() {
parent::__construct();
if (!$this->session->userdata('logged_in')) {
redirect('YourLoginController');
}
}
This should definitely be in the controller.
You could also create a base controller to extend your regular CI_Controller, look up the MY_Controller concept in the docs. In there, you could add a method that checks for authentication and redirects if not, and then call it in your controller methods that require authentication:
class MY_Controller extends Controller{
public $data = array();
function _construct() {
parent::_construct();
$data['logged_in'] = $this->session->userdata('logged_in');
}
function authenticated() {
if (!$this->data['logged_in']) {
redirect('YourLoginController');
}
}
}
And then in YOUR controller:
class Some_Controller extends MY_Controller {
function _construct() {
parent::_construct();
}
// If a method requires authentication
function someMethod() {
$this->authenticated(); //This does nothing if logged in
//It redirects to login if not logged in
//Your stuff.
}
//If a method DOESN'T require login, your $this->data to
//pass to the view has already been started from MY_Controller
//so append the display content you need to that array and
//then pass it to the view
function someOtherMethod() {
$this->data['somecontent'] = "I'm content";
$this->load->view('someView',$this->data);
}
}
Using a concept created from the someOtherMethod() you could then utilize the variable $logged_in in your view to change the content based on a user's authentication status.
The code is better placed in a controller so you can show the proper view based on whether the user is logged in or not. Secure? What are are you trying to avoid? With CI that's the most common way to check and see if a user is currently logged in...as long as you set the is_logged_in variable properly.
While the code will work both in view and controller files, it's a better idea to keep the code in controller not only for the sake of MVC philosophy, but it is also more efficient to keep it in controller.
The reason is that your view files are loaded from controllers. This means that if a user is not logged in, your controller&view files will be still interpreted although they don't have to be. If you check the session in controller, once the controller learns that the session is missing, it can stop interpreting the rest of the code and do some other action such as redirecting user to pages that don't require authentication.
I am currently using the codeigniter tank_auth, at the start of every controller method I have to do the following:
$data['profile'] = $this->tank_auth->get_profile();
The main reason I do this is to display the current logged in username, and also get their privilege level.
I am going over the code trying to go by the DRY principle and have moved a lot of repeated code over to the _constructor method (Like checking if the user is logged in). I am just wondering if there is a way to move this code from the start of every method to the constructor.
My current constructor method looks like so:
public function __construct()
{
parent::__construct();
// If the user isn't logged in redirect to login page.
if (!$this->tank_auth->is_logged_in())
redirect('auth/login');
}
Thanks!
Add variable $data to the controller and use it for all your view data. For example:
public function __construct()
{
parent::__construct();
$this->data['profile'] = $this->tank_auth->get_profile();
}
When calling the view remember to call it like this:
$this->load->view('my_view', $this->data);
You can also extend CI_Controller with MY_Controller and put the login check in the constructor of MY_Controller. Just extend all controllers which need this check from MY_Controller instead of CI_Controller.
I'm using HMVC in CodeIgniter https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/wiki/Home
How do I setup a controller that would automatically run when accessing a user-only page.
This is for the purpose of checking if a user is currently logged in or not. I've already made a helper to check if user is logged in:
<?php
if(!defined('BASEPATH')) exit('No direct script access allowed');
if (!function_exists('is_logged_in')){
function is_logged_in(){
$CI =& get_instance();
$logged_in = FALSE;
$user_data = $CI->session->userdata('logged_in');
if(!empty($user_data)){
$logged_in = TRUE;
}
return $logged_in;
}
}
But the only thing that I know is to call this method on the constructor of each controller on each of the modules. I would be repeating the same code on every controller just to check if the user is logged in. Basically I want this function to be called everytime a user tries to access something inside the modules directory.
You can use _remap() for this. You can put this in MY_Controller if you are using one, for more information read the Controller User Guide
Here is something you can start with.
function _remap($method)
{
if (method_exists($this, $method) && $this-my_custom_helper->is_logged_in())
{
$this->$method();
}
else
{
redirect('/auth/login/');
}
}
One option is to extend the main controller class(CI_contorller I guess) and call this helper method in the that controller's constructor. Then extend all the other user related controller from this new controller.
I'm fairly new to CodeIgniter and I'm using Ion Auth for user authorization. With the Ion Auth library, you get a user object like:
$user = $this->ion_auth->get_user();
echo $user->email;
If a user is logged in, I want the $user object to be available on any of the pages (in any of the controllers). How can I do this? (I'm using CodeIgniter 2)
This blog post of mine goes into a lot of detail in specifically using Ion_Auth to allow your entire application (including views) to access your current user's information.
The short version... (specifically for the topic at hand)
Adding this to your MY_Controller.php file
class User_Controller extends CI_Controller {
protected $the_user;
public function __construct() {
parent::__construct();
if($this->ion_auth->logged_in()) {
$data->the_user = $this->ion_auth->get_user();
$this->the_user = $data->the_user;
$this->load->vars($data);
}
else {
redirect('/');
}
}
}
Then in your application just create your controller like this
class App_Controller extends User_Controller {
public function __construct() {
parent::__construct();
}
function index() {
//do stuff
}
}
Then not only in your controller will you have access to $this->the_user but you will also have $the_user loaded into every view with $this->load->vars()
Normally you'd cache something like this in the session, however I've moved away from that in most of my CI apps.
An example: you log the user in (caching the user data) and then they go to update their email on their profile page. You now have to reload you cache. Many other things could drive this reload. Usually the most I cache any more is the ID, then I do what you're doing and get the user's data on any page I need it.
One thing I found that helps is to have base controllers. For example I have a RegisteredUserController. Any controller whose actions all require the user to be logged in extend this. That way I can keep the logged in check and things like get the user data in one spot (in the constructor). For example:
class RegisteredUserController extends CI_Controller {
var $user;
function __construct() {
parent::__construct();
$this->user = $this->ion_auth->get_user();
}
}
Then any controller that extends RegisteredUserController instead of just controller can get to the user with $this->user. Following this pattern would get it on every page (that extends the controller) without resorting to caching.