使用CGI :: Session的Perl Web登录脚本

时间:2016-09-09 14:36:53

标签: perl cgi

我差不多两周前就遇到了同样的问题。 我是Perl和Web的新手:/

我按照CGI :: Session教程和Cookbook,代码似乎很好但是......不工作。

  

的index.cgi

#!/usr/bin/perl
use CGI;
use CGI::Cookie;
use HTML::Template;
use strict;
use warnings;
use CGI::Session;
use CGI::Carp qw(fatalsToBrowser);
require "cgi-bin/web_base.pl";
require "cgi-bin/login.pl";

my $cgi = new CGI;
my $session = new CGI::Session("driver:File", undef, {Directory=>'/tmp'}) or die CGI::Session->errstr;
my $CGISESSID = $session->id();
print header();
print $cgi->header();
print my_topbar();
login_attempt($session, $cgi);

if ( $session->param("~login-trials") >= 3 ) {
    print error("You failed 3 times in a row.\n" .
                "Your session is blocked. Please contact us with ".
                "the details of your action");
    exit(0);

}

unless ( $session->param("~logged-in") ) {
    print login_form($cgi, $session);
    exit(0);

}
print footer();
  

login.cgi

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Cookie;
use HTML::Template;
use CGI::Session;
use CGI::Carp qw(fatalsToBrowser);
use Fcntl;

my $cgi = new CGI;      
my $session = new CGI::Session(undef, $cgi, {Directory=>'/tmp'});
sub login_attempt {
    my ($session, $cgi) = @_;

    if ( $session->param("~logged-in") ) {
        return 1;  # Verify if user is not logged.
    }

    my $username = $cgi->param("username") or return;
    my $password=$cgi->param("password") or return;

    # Form submited. Try to load profile.

    if ( my $profile = load_profile($username, $password) ) {
        $session->param("~profile", $profile);
        $session->param("~logged-in", 1);
        print "YOUPIIIII";
        $session->clear(["~login-trials"]);
        $session->redirect("dashboard.cgi");
        return 1;
    }

    # Failed to login, wrong credentials.

    my $trials = $session->param("~login-trials") || 0;
    return $session->param("~login-trials", ++$trials);
}
return 1;

sub load_profile {
    my ($username, $password) = @_;

    local $/ = "\n";
    unless (sysopen(PROFILE, "profile.txt", O_RDONLY) ) {
        die ("Couldn't open profile.txt: $!");
    }
    while ( <PROFILE> ) {
        /^(\n|#)/ and next;
        chomp;
        my ($n, $p) = split "\s+";
        if ( ($n eq $username) && ($p eq $password) ) {
            my $p_mask = "x" . length($p);
            return {username=>$n, password=>$p_mask};

        }
    }
    close(PROFILE);
    return undef;
}

profile.txt

Formget    123

当我尝试登录时,没有任何事情发生,即使我尝试错误的crendentials它应该在3次尝试后阻止我,但事实并非如此。

有人可以真的帮助我吗?我无法忍受它。

随时提出任何问题:)

编辑:

-login_attempt()更正了

-load-profile不起作用,换了新的,但仍然需要改进。

- 最后问题是会话初始

1 个答案:

答案 0 :(得分:2)

您确定没有收到任何错误吗?您是否检查过Web服务器错误日志?

您使用两个参数(login_attempt()$session)调用$cgi但在login.cgi中,该子例程的定义如下:

sub login_attempt() {
  ...
}

您(可能是偶然)在该子例程上使用原型,告诉Perl它不需要参数。如果你没有收到错误的话,我会感到惊讶:

  

main :: login_attempt

的参数太多

从该定义中删除括号。

sub login_attempt {
  ...
}

更新:我认为你在这里错过了一个非常重要的步骤。来自CGI::Session Tutorial

  

在创建CGI :: Session对象之后,应用程序需要执行一个小但非常重要的事情。它需要将会话ID作为HTTP cookie丢弃到用户的计算机中。 CGI :: Session将使用此cookie在他/她的下一个请求中识别用户,并且能够加载他/她以前存储的会话数据。

     

为了确保CGI :: Session能够在下次请求时读取您的cookie,您需要查询其name()方法以获取cookie的建议名称:

$cookie = $query->cookie( -name   => $session->name,
                          -value  => $session->id );
print $query->header( -cookie=>$cookie );
     

name()默认返回CGISESSID。如果您更喜欢不同的cookie名称,也可以轻松更改它,但必须在创建CGI :: Session对象之前进行更改:

CGI::Session->name("SID");
$session = CGI::Session->new();
     

烘烤饼干并不太难,是吗?但是有一种更简单的方法可以使用CGI :: Session发送cookie:

print $session->header();
     

以上将使用CGI :: Cookie创建cookie,并使用CGI.pm的CGI方法返回正确的http标头。 CGI :: Session的任何参数都将传递给CGI :: header()。

如果没有这个,您将为每个请求创建一个全新的会话。