【问题标题】:Correct using of CGI::Session, Perl正确使用 CGI::Session、Perl
【发布时间】:2014-01-22 15:12:48
【问题描述】:

我需要通过登录名和密码保护我网站上的所有页面。我有一个入口点,所以它不会那么难。它现在正在运行,但我想改进授权系统(是的,它可以工作,但我希望它能够正常工作)。

检查登录名和密码的代码是这样的:

my $sth = $dbh->prepare(qq{select count(*) from admin where login = '$input_login' and password = '$input_password_hash'});
$sth->execute();
($count) = $sth->fetchrow_array();
$sth->finish();
if ($count eq 1) 
{
    $session->param("user_logged_in", 'true');
    print '<META http-equiv="refresh" content="0;URL=/">';
}

关于它的2个问题: 1)它完全正确吗? 2)最终用户的脚本行为是这样的:用户写入他的登录名和密码,发送表单,再次加载登录页面,然后(重定向到空白字段的登录页面并显示 1 秒)受保护的数据出现。如何删除显示登录空白表单并立即登录?输入登录名和密码,发送表单和数据立即显示,而不是在显示空白登录 1 秒后显示。我认为这是关于元重定向。你怎么看?
这是前 2 个问题。

当用户单击另一个链接或在一段时间后重新访问该站点时,我们是否应该再次创建一个新会话?绝对不是。

引用CGI::SessionCGI::Session Tutorial 的文档。

它说,我应该首先检查用户会话是否存在,如果不存在,将创建新会话。代码应该是这样的:

$cgi = new CGI;
$sid = $cgi->cookie("CGISESSID") || undef;
$session = new CGI::Session(undef, $sid, {Directory=>'../tmp'});

但对我来说,这段代码也可以正常工作(我可以访问会话变量):

$session = new CGI::Session(undef, undef, {Directory=>'../tmp'});

3) 你能解释一下为什么这段代码有效吗?第一个代码也可以。但是第二个代码(没有 $sid 作为第二个参数)不能工作(但它可以工作)。

关于从会话中访问数据的问题:

$authorised = $session->param("user_logged_in");

4) 以这种方式访问​​会话变量是否正确?
5) 如果我需要访问其他脚本上的$session 怎么办?我应该如何访问$session

【问题讨论】:

    标签: perl session authorization


    【解决方案1】:

    (1)

    首先,您有一个 SQL 注入漏洞:

    改变这个:

    my $sth = $dbh->prepare(qq{
       select count(*) from admin 
       where login = '$input_login' and password = '$input_password_hash';
    });
    $sth->execute();
    

    到这里:

    my $sth = $dbh->prepare(qq{
       select count(*) from admin 
       where login = ? and password = ?;
    });
    $sth->execute($input_login, $input_password_hash);
    

    (2)

    不要从 HTML 执行客户端 (META-EQUIV) 重定向,而是执行由服务器发起的客户端重定向 (HTTP)。

    变化:

    print '<META http-equiv="refresh" content="0;URL=/">';
    

    收件人:

    print $cgi->header('Redirect: /');
    

    (3)

    我最近没有像这样直接使用 CGI::Session,但我猜它的设计目的是在默认情况下为你调用 new CGI()

    我不会那样做;我会直接打电话给new CGI()编辑: 示例:

    my $sparams = { name => 'MY_APP' };
    my $cgi     = CGI::Simple->new;
    my $session = CGI::Session->new(undef, $cgi, {}, $sparams);
    
    # use $cgi for GET/POST params
    # use $session for header & session storage.
    
    print $session->header;
    my $sval = $session->param('some-session-var');
    my $opt1 = $cgi->param('some-get-var');
    

    (4)

    是的,没关系。

    (5)

    然后在其他脚本中实例化会话。您需要匹配 cookie namepath 和存储方法(使用默认值即可实现)。

    【讨论】:

    • 感谢您的回答!明天要试试这个。关于2的问题。$cgi-&gt;header('Redirect:/');会导致错误headers were already sent吗? Content-type: text/html\n\n 尚未打印。
    • 是的,如果您已经发送了Content-type: 标头,它会说。所以不要那样做! :-) 在发送Content-type: 标头之前,请等到您知道自己是否要执行某件事。
    • 你在(3)答案中是什么意思?你直接拨打new CGI()?这是什么意思?如何?你能举个例子吗?我的示例正在运行,但我不知道为什么 :( 我的代码无法运行。$session = new CGI::Session(undef, undef, {Directory=&gt;'../tmp'}); 还有关于 (5) 的回答:我应该以同样的方式初始化会话?
    • 您所做的并没有错。我通常只是将两个构造函数调用分开以使其更易于理解。 (我已经通过回答进行了编辑以给出一个“默认”示例)。
    • 你能解释一下这段代码的前 3 行吗?还有print $session-&gt;header;?和我的有什么区别?我通过js设置cookie,所以浏览器知道会话。没事吧?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    • 2014-01-29
    • 2012-10-11
    • 2021-04-29
    • 2015-06-09
    相关资源
    最近更新 更多