【问题标题】:How to redirect using Perl?如何使用 Perl 重定向?
【发布时间】:2014-10-10 06:28:05
【问题描述】:

我是 Perl 新手,当用户输入正确的密码时,我正尝试将用户重定向到我服务器上的另一个页面。我要重定向到的页面(hello.pl)与页面的 Perl 脚本位于同一目录中;但是,当我尝试重定向时,我得到的只是一条消息:

Status: 302 Found Location: hello.pl

但浏览器实际上并没有转到我想要的 hell0.pl。我在网上和 Perl 书籍中查看,但看起来我做的一切都是正确的,有人能告诉我为什么我的代码没有重定向吗?这是它的代码: 我省略了设置页面和获取存储在 $var 中的用户输入的代码,即我在文件顶部做了 $var = CGI->new,而且我使用 CGI.pm 作为库。

#!/usr/bin/perl -wT
use strict;

use CGI qw(:standard);

print header,
      start_html("Input Form"),
      start_form,
      "Please enter your username:",
      textfield(-name=>'username',
                      -maxlength=>20),p,
      "Please enter your password:",
      password_field(-name=>'password',
                      -maxlength=>20),p,
      submit,
      end_form,
      hr, "\n";

my $var = CGI->new;
my $username  = $var->param("username");
my $password  = $var->param("password");

my $open = "opensesamie";

  if ($password ne $open) {
          print "Sorry wrong password";
  } else {
          print $var->redirect('hello.pl');
          print $var->start_html,p,
          "Hello, $username",p,
          "The current time is ",scalar(localtime),
          $var->end_html;
  }

print end_html;

【问题讨论】:

  • @Borodin 我并不是要暗示您不知道这些变量是什么,这正是我选择的称呼。我不知道您是否看过我上面关于包含标题的 cmets,但我进行了编辑以使其清楚,如果我使用您最初发布的代码,那么我仍然没有重定向。
  • 我的回答错了,前段时间我删了。我道歉。无需将这些 use 语句放在程序顶部之后的任何位置。也不需要header调用或start_html/end_html调用,应该只有一个redirect。你是如何运行你的 CGI 程序的?如果您只是从命令行运行它,那么这就是您应该看到的所有内容。您需要通过从 wrb 浏览器加载 CGI 脚本来执行它。是 Web 浏览器看到 302 状态,然后加载Location 地址。
  • 你误会了。您应该永远调用 anything var,因为它没有描述变量的用途。
  • 好的,我将删除编辑,我明白你关于 var 的观点,谢谢,下次写代码时我会记住它。
  • 你的程序运行得如何?你在哪里看到你描述的输出?

标签: perl redirect cgi


【解决方案1】:

您正在输出两个标题。不要将headerredirect 用于同一个请求。

#!/usr/bin/perl -wT
use strict;

use CGI qw(:standard);

my $cgi = CGI->new;
my $username  = $cgi->param("username");
my $password  = $cgi->param("password");

if ($password eq "opensesamie") {
   print $cgi->redirect('hello.pl');
   exit();
}

print header;
print start_html("Please Login");
print p({-class => "error"}, "Incorrect password") if $password;
print ... print the form here ...;

【讨论】:

  • 对不起,我不明白,我在哪里调用标头,然后在同一个对象上重定向?在我调用 set $var = CGI->new 之后,如果密码错误,我只调用一个标头,否则我调用重定向。
  • 关于“我只在密码错误时才调用标头,否则我会调用重定向。”,这就是你应该做的(正如我所说并在我的回答中显示的那样),但你实际上无条件地致电print header
  • 感谢您的回答,但我之所以选择 Bodin 的回答是因为他花了很多时间设置服务器并试图帮助我,但我同意您的代码更胜一筹。
【解决方案2】:

我认为你有这样的东西。

您是否在测试密码的if 之前的某个地方启动了HTTP print 语句?这将使print $cgi->redirect 的标题只是HTML 文本的一部分。

use strict;
use warnings;

use CGI;

my %passwords;

my $cgi = CGI->new;

my $username = $cgi->param('username');
my $password = $cgi->param('password');

print
   $cgi->header,
   $cgi->start_html;

if ($password ne $open) {
   print 'Sorry wrong password';
}
else {
   print $var->redirect('hello.pl');
   print
      $var->start_html, p,
      "Hello, $username", p,
      "The current time is ", scalar(localtime),
      $var->end_html;
}      

你需要把成功/失败完全分开,像这样

use strict;
use warnings;

use CGI;

my %passwords;

my $cgi = CGI->new;

my $username = $cgi->param('username);
my $password = $cgi->param('password);

my $open = $passwords{$username};

if ($password ne $open) {
   print
      $cgi->header,
      $cgi->start_html;
      $cgi->p('Sorry wrong password'),
      $cgi->end_html;
}
else {
   print $var->redirect('hello.pl');
}      

【讨论】:

  • 我做了你在我的代码中建议的更改,但仍然没有重定向,但它只是打印:状态:302 找到位置:hello.pl
【解决方案3】:

抱歉耽搁了 - 我必须设置一个有效的 HTTP 服务器来测试我的代码。

感谢您发布完整代码。正如我所猜测的那样 - 您已经在程序顶部开始了一条消息,然后将redirect 输出添加到它,而您需要发送到客户端的重定向输出。

我认为这就是您所需要的。它检查是否已发送 usernamepassword 参数。如果没有,则必须显示表格以要求他们。如果是这样,那么如果密码错误则必须发送错误消息,或者如果密码正确则重定向。

#!/usr/bin/perl

use strict;
use warnings;

use CGI qw(:standard);

my %names = map { $_ => 1 } param;
my $open  = 'opensesamie';

if ($names{username} and $names{password}) {

   my $username = param('username');
   my $password = param('password');

   if ($password eq $open) {
      print
         header,
         start_html,
         p('Sorry, wrong password'),
         end_html;
   }
   else {
      print redirect('hello.pl');
   }
}
else {

   print
      header,
      start_html('Input Form'),
      start_form,
         p('Please enter your username:'),
         textfield( -name => 'username', -maxlength => 20),
         p('Please enter your password:'),
         password_field( -name => 'password', -maxlength => 20),
         p,
         submit,
      end_form,
      hr,
      end_html;
}

【讨论】:

  • 感谢您花时间设置服务器并编写此代码,您能否向我解释一下行:my %names = map { $_ => 1 } param;有吗?
  • @Stochastic13: param 返回传递给 CGI 程序的参数名称列表。 map 调用创建一个散列,使用这些名称作为键,每个值使用 1。通过编写if ($names{param_name}) { ... },检查是否已传递给定参数变得非常简单。在这种情况下,我使用它来检查用户名和密码参数是否都通过编写if ($names{username} and $names{password}) { ... }
  • 我之前的回答比这个的优点是,如果您输入了错误的密码,它可以让您有机会重新输入密码
猜你喜欢
  • 2011-01-27
  • 1970-01-01
  • 2014-10-10
  • 2015-03-18
  • 2017-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多