将特定页面限制为仅在 Codeigniter 中登录用户的最佳实践是啥?

Posted

技术标签:

【中文标题】将特定页面限制为仅在 Codeigniter 中登录用户的最佳实践是啥?【英文标题】:What is the best practice for restricting specific pages to logged in users only in Codeigniter?将特定页面限制为仅在 Codeigniter 中登录用户的最佳实践是什么? 【发布时间】:2011-04-18 16:05:10 【问题描述】:

我已经为我的网站创建了一个注册和登录,并且所有验证都适用于注册和登录。用户提供有效凭据后,他/她将使用欢迎消息登录到会员区,上面写着 Hello first_name last_name.. 基本上名字和姓氏都是从数据库中获取的。

我想做的任何方式都是将会员区限制为仅登录用户。其他任何人都将被重定向到主页或登录页面,或者我决定将他们重定向到的任何地方。

我使用了 ci_sessions,它存储在我的数据库中的“ci_sessions”表中。 Session_id、ip_address、user_agent、last_activity 和 user_data 是这些列。所以我想这是某种形式的安全性,而不是仅将 cookie 存储在用户浏览器上。

无论如何,现在阻止除了登录用户之外的任何其他人访问我的网站会员区域,例如http://example.com/member_area 我在控制器中为成员区使用了一个简单的 if 语句:

if (! $this->session->userdata('first_name'))
    
    redirect('login');

这将检查试图访问成员区域页面的人是否在我的 ci_sessions 表中的 user_data 中存储了某种数据,例如 first_name,如果有,则允许他们访问该页面,这意味着他们必须已经登录并且仍然有一个活跃的会话。

如果在数据库中没有找到任何东西,它们将被重定向到网站登录页面。我想知道是否有更好的方法来做到这一点?我现在的做法是否足够安全?

下面是我的型号代码:

<?php
class Current_User 

    private static $user;

    private function __construct() 

    public static function user() 

        if(!isset(self::$user)) 

            $CI =& get_instance();
            $CI->load->library('session');

            if (!$user_id = $CI->session->userdata('user_id')) 
                return FALSE;
            

            if (!$u = Doctrine::getTable('User')->find($user_id)) 
                return FALSE;
            

            self::$user = $u;
        

        return self::$user;
    


    public static function login($email, $password) 

        // get User object by email
        if ($u = Doctrine::getTable('User')->findOneByEmail($email)) 


            // to ge the mutated version of the input password
            $u_input = new User();
            $u_input->password = $password;

            // password match
            if ($u->password == $u_input->password) 


                $CI =& get_instance();
                $CI->load->library('session');
                $CI->session->set_userdata('user_id',$u->id);
                $CI->session->set_userdata('username',$u->username);
                $CI->session->set_userdata('first_name',$u->first_name);
                $CI->session->set_userdata('last_name',$u->last_name);

                self::$user = $u;

                return TRUE;
            

            unset($u_input);
        

        // login failed
        return FALSE;

    


    public function __clone() 
        trigger_error('No duplicates allowed.', E_USER_ERROR);
    


感谢您的所有建议。

更新

如何将它添加到我的模型中

$CI->session->set_userdata('logged_in', 'TRUE');

这基本上将“logged_in”添加到我在数据库会话中的用户数据中,值为“TRUE”。 在我的“会员区”控制器中,我编辑了 if 语句来说明:

if (! $this->session->userdata('logged_in')==TRUE)

redirect('login');

如果该项目不存在“如果用户未登录则不存在”,则将返回 FALSE 并将用户重定向到登录页面

你怎么看?

或者我什至可以将 TRUE 设为秘密,例如 dsb453rerfksdhbdsks322。随机的东西。

【问题讨论】:

【参考方案1】:

您已经一针见血了,但是有一种更有效的方法来做到这一点。

以一种方式扩展基本控制器(我相信最初由 Phil Sturgeon 概述),但我将在此总结:

请参阅 this article 以获得非常深入的文章。

但本质上:

<?php
class MY_Controller extends Controller

    function __construct()
    
        parent::Controller();
        if (! $this->session->userdata('first_name'))
        
            redirect('login'); // the user is not logged in, redirect them!
        
    

所以现在如果你想限制访问,只需:

class Secret_page extends MY_Controller 

 // your logged in specific controller code

并且扩展控制器会在构造函数中自动检查用户是否登录。

至于如何,我可能会将 user_id 设置为值以检查其是否设置,或者可能是用户“组” - 然后您可以获得用户权限和系统中不同级别的访问权限。

希望这会有所帮助。

编辑

将此添加到 application/config.php

/*
| -------------------------------------------------------------------
|  Native Auto-load
| -------------------------------------------------------------------
| 
| Nothing to do with cnfig/autoload.php, this allows PHP autoload to work
| for base controllers and some third-party libraries.
|
*/
function __autoload($class)

    if(strpos($class, 'CI_') !== 0)
    
        @include_once( APPPATH . 'core/'. $class . EXT );
    

当您使用 CI 2.0 时,您需要将 MY_Controllers 放在 Application/CORE 而不是库中。

我的应用程序/核心看起来有点像:

Admin_Controller.php
MY_Controller.php
Public_Controller.php

【讨论】:

是的,非常感谢。我将阅读 Phil Sturgeon 的文章以获得更好的理解。我注意到的另一件事是,即使我没有登录会话 id,user_agent、ip、last_active 也会在数据库中存储/更新。现在我可以想象数百万人在没有登录的情况下浏览该网站。这很糟糕吗?它不应该只记录登录用户的信息吗?如果没有,如果用户没有登录,有没有办法让它销毁这些数据或根本不记录它? 致命错误:在...中找不到类 'MY_Controller' 我认为这是一个 codeignitet 2.0 错误 nada,你需要使用 PHP5s 的自动加载魔法。查看我编辑的帖子【参考方案2】:

我使用类似的东西:

    $user_session = $this->model_user_lite->Session_Check();
    if ( $user_session == FALSE )
    
        redirect('main/about');
        exit();
    
    $data['auth'] = $user_session;
    $user_id = $this->model_user_lite->Session_UserID ();

保护自己的功能而不是控制器,在我看来这更有效。 该代码非常自我解释,但是我也进行了会话检查:

function Session_Check ( $return_link = FALSE )


    $auth   = $this->session->userdata('logged_in');
    if ( $auth == FALSE )
    
        $return_value = FALSE;
    
    else
    
        $return_value = TRUE;
    

    return $return_value;


所以在用户登录的地方,我们只需将用户数据“logged_in”设置为 TRUE 并随时检查。

希望对你有帮助!

【讨论】:

【参考方案3】:

我不认为实现安全性是控制器的工作,它应该只是检查它。您可以将身份验证逻辑编码到库中。接下来,自动加载该库。在提供受保护内容的控制器方法中,您可以简单地执行以下操作:

$this->auth->restrict();

【讨论】:

以上是关于将特定页面限制为仅在 Codeigniter 中登录用户的最佳实践是啥?的主要内容,如果未能解决你的问题,请参考以下文章

将 jQuery .keydown() 限制为仅特定键

如何将查找和替换限制为仅 CSV 中的一列?

WPF:将复选框的可点击区域限制为仅限复选框

CodeIgniter 仅在某些页面使用 CSRF 保护

多个类似子句 Codeigniter

将本地通知设置为仅在清醒时间触发