GeckoエンジンでのLocationヘッダについて

このQ&Aのポイント
  • セッションの管理とGeckoエンジンでのLocationヘッダについて説明します。
  • CGIリクエストでCookieを使わずにセッションIDを送信する方法について質問しています。
  • Geckoエンジンではセッションが切れた時やセッションファイルを削除した時におかしな動作をする問題があります。
回答を見る
  • ベストアンサー

続Gecko エンジンでの Location ヘッダについて

Gecko エンジンでの Location ヘッダについて http://oshiete1.goo.ne.jp/qa4227374.html の続きです。 なんだかよく分からない状況になったのでより実際の処理とほぼ同様の 処理を行っているサンプルを用意しました。 # セッション管理 use strict; use CGI::Session; &main(); # メイン sub main { my $cgi = &getreq(); print "Pragma: no-cache\n"; print "Cache-Control: no-cache\n"; # セッション取得 my $session = &session($cgi); # セッションが取得できない場合、再取得 if($session == undef) { # print "Content-type: text/plain\n\n"; # print "CGISESSID=$cgi->{'CGISESSID'}\n"; $session = &session({}); # セッション ID を取得してリダイレクト my $id = $session->id(); print "Location: ./?CGISESSID=$id\n\n"; exit; } my $id = $session->id(); if($cgi->{'CGISESSID'} eq '' || $cgi->{'CGISESSID'} ne $id) { # print "Content-type: text/plain\n\n"; # print "CGISESSID=$cgi->{'CGISESSID'}\n"; # セッション ID が指定されていないまたは # セッション ID が異なる場合リダイレクト print "Location: ./?CGISESSID=$id\n\n"; exit; } print "Content-type: text/plain\n\n"; print "CGISESSID=$id\n"; print "OK\n"; exit; } # CGI リクエストの取得 sub getreq { my $cgi = {}; my $query = ''; $query = $ENV{'QUERY_STRING'}; my @args = split(/&/, $query); foreach my $i (@args) { my ($name, $val) = split(/=/, $i); $val =~ tr/+/ /; $val =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig; $name =~ tr/+/ /; $name =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig; $cgi->{$name} = $val; } delete($cgi->{''}); return $cgi; } # セッション取得 sub session { my $cgi = shift; my $dir = { 'Directory' => 'tmp' }; CGI::Session->find(undef, sub {}, $dir); if($cgi->{'CGISESSID'} eq '') { my $session = new CGI::Session(undef, undef, $dir); $session->expire("1h"); return $session; } my $session = CGI::Session->load(undef, $cgi->{'CGISESSID'}, $dir); return ($session == undef || $session->id() eq '') ? undef : $session; } こんな感じのCGIで以下のような状況の時にページを更新すると IE(Trident)/Opera(Presto)及びSafari for Win(WebKit)では 正常に動作するのですがFxやSeaMonkey(Gecko)ではおかしな動作を します。 1. セッションが切れた時 2. セッションファイルを手動で削除した時 具体的にはセッションが切れたら再度新しいセッションを作成して リダイレクトをするようにしてあるのですがGeckoでは一度セッションが 切れると更新する度に新しいセッションを作成するようになってしまい ます。 以前の質問の回答のように Status: 303 See Other ヘッダを出力して 見たのですがやはり効果はないようです。 Cookieは使いたくないのでセッションID(sesid)をCGIリクエストで 送信しているのですがこの方法がまず問題なのでしょうか。 他にも問題のある部分がありましたらご指摘お願いします。

  • CGI
  • 回答数1
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.1

直接の回答ではありませんが、 HTTPプロトコルでの「Location:」ヘッダは、規格上は絶対URLを指定することになっています。相対では指定できません。 http://www.studyinghttp.net/rfc_ja/rfc2616#Sec14.30 実際には相対URLでもたいていの場合うまく動作するようですが、 規格外のデータを受け取った時のブラウザの挙動は当てにするべきでないと思います。 まずは絶対URLを返すようにしてみてはどうでしょうか?

pick52
質問者

お礼

今更ですが上手く解決できないので別の方法で対応することにしました。 お返事ありがとうございました。

pick52
質問者

補足

ありがとうございます。 > HTTPプロトコルでの「Location:」ヘッダは、規格上は絶対URLを > 指定することになっています。相対では指定できません。 > ​http://www.studyinghttp.net/rfc_ja/rfc2616#Sec14.30​ > 実際には相対URLでもたいていの場合うまく動作するようですが、 > 規格外のデータを受け取った時のブラウザの挙動は当てに > するべきでないと思います。 > まずは絶対URLを返すようにしてみてはどうでしょうか? 知っていたのですが、とりあえず基本的なブラウザではどれでも 相対パスで動作していたので問題ないかなと思ってやっていました。 やはり、絶対パスでやった方がいいんでしょうかね。 http://www.studyinghttp.net/header によると Content-Location の方は相対パスも受け付けるみたい なんですけど Location はなんで絶対パスなんでしょうか。 で、ここでいう絶対パスって完全なURLなのか / から始めていいのかも 分からなくて両方とも試してみましたがやはり変わらないようです。 print "Location: $ENV{'SCRIPT_NAME'}?CGISESSID=$id\n\n"; print "Location: http://$ENV{'HTTP_HOST'}$ENV{'SCRIPT_NAME'}?CGISESSID=$id\n\n";

関連するQ&A

  • Gecko エンジンでの Location ヘッダについて

    以前に投稿したのですが回答が得られなかったので削除して再質問です。 Gecko エンジンで Location ヘッダを送信してリダイレクトした後の ページで更新(ページリロード)すると反応がおかしいようです。 例えば a というページから b というページにリダイレクトをして b で更新をかけるとページの URL は a であると判断されてしまうよう です。 # 検証用 CGI (index.cgi) use strict; &main(); sub main { my $cgi = &getreq(); my $min = (localtime())[1]; # キャッシュしない print "Pragma: no-cache\n"; print "Cache-Control: no-cache\n"; if($cgi->{'min'} eq '') { # $cgi->{'min'} が空なら # (Gecko では更新した時にもこっちにくる) print "Location: ./?min=$min\n\n"; exit; } elsif($cgi->{'min'} ne $min) { # 分が異なる場合 (Gecko はこない) print "Content-type: text/plain\n\n"; print "\$cgi->{'min'}=$cgi->{'min'}\n"; exit; } # $cgi->{'min'} と $min が同じ print "Content-type: text/plain\n\n"; print "min=$min\n"; exit; } sub getreq { my $cgi = {}; my $query = ''; $query = $ENV{'QUERY_STRING'}; my @args = split(/&/, $query); foreach my $i (@args) { my ($name, $val) = split(/=/, $i); $val =~ tr/+/ /; $val =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig; $name =~ tr/+/ /; $name =~ s/%([0-9a-f]{2})/pack('C', hex($1))/eig; $cgi->{$name} = $val; } delete($cgi->{''}); return $cgi; } CGI::Session でセッション管理をしようとしたところ、IE(Trident)と Opera(Presto)では正常なのですがFirefoxでうまく動作しなかったので よく調べてみたところこのような状態です。 どうにかならないでしょうか。 因みに、後で調べてみるとSafari(WebKit) for Winでも正常でした。 現象が発生するのはGeckoのみです。 (Fxの他、SeaMonkeyでも同様の現象を確認しています)

    • ベストアンサー
    • CGI
  • hiddenを使ったセッション

    こんにちは。 セッションを使ったデータの受け渡しをしたいのですが、 (携帯を考慮してcookieは使わないやり方で) hiddenにセッションIDを持たせる方法で書いてみたのですが、 うまくいきません。 送られてはいるけど、受け取れていないのかな…? とは思うのですが、対処がわかりません。 以下のソースです。(確認用でGETにしてます) 望むのは、printされたセッションIDとテキスト内のセッションIDが 同一になる(=セッションが保持できてるということですよね?) かつ、submitしても、セッションIDが変わらない、という状況です。 よろしくお願いいたします。 print "Content-type: text/html\n\n"; use CGI; use CGI::Session qw/-ip-match/; if ($ENV{'REQUEST_METHOD'} eq "POST") { read(STDIN, $query_string, $ENV{'CONTENT_LENGTH'}); } else { $query_string = $ENV{'QUERY_STRING'}; } my $cgi = new CGI; CGI::Session->name("session_id"); my $session = new CGI::Session("driver:File", $cgi, {Directory=>'./session'}); $sid = $session->id(); $session->param('value', $sid); $sesid = $session->param('value'); print $sesid."<br>\n"; undef($session); @query = split(/&/, $query_string); foreach $query (@query){ ($name, $data) = split(/=/, $query); $data{$name} = $data; } print <<"EO"; <html><head> <title> </title> </head> <body><hr><hr> <form action="./test.cgi" method="GET"> <input type="hidden" name="session_id" value="$sesid"> <input type="text" name="btn" size="50" value="$data{'session_id'}"><br> <input type="submit" value="submit"><br> </form> <hr><hr></body></html> EO

  • "use CGI::Session"でエラーが発生してしまいます

    初投稿です。宜しくお願いします。 ActivePerl5.8.0+Apache1.3.14でSessionを使用した Webサイトを作成中なのですが、 ppm経由でインストールしたCGI::Sessionを useしようとしても、エラーになってしまいます。 サンプルコードは以下の通りです。 #!/usr/bin/perl use CGI::Session; &ses(); &print(); sub ses() { # Session作成・ここから my $session = new CGI::Session(undef, undef, {Directory => './tmp'}); my $tmpSID = $session->id(); $session->param('menu', 'MENU1'); $session->expire('+2h'); $session->header(); } sub print() { print "Content-type: text/html;charset=ISO-2022-JP\n\n"; print <<EOF; OK! EOF } use CGI::Session; の部分(と、Session関数を 呼び出している部分)をコメントアウト すると、とりあえずはエラーが出なくなるので、 原因はここだとわかっているのですが、 文法的に間違っているとは思えないですし、 困っています。 情報お願いいたします。

    • ベストアンサー
    • Perl
  • CGI::Session

    http://perldoc.jp/docs/modules/CGI-Session-3.11/Session.pod 上記サイトを参考に、 use CGI::Session; my $session = new CGI::Session("driver:File", undef, {Directory=>'/tmp'}); my $CGISESSID = $session->id(); を稼動中の掲示板CGIに組み込んでみたところ、$session がnullになるようで、$session->id()のところでエラーになってしまいます。 (use CGI::Session;の行ではエラーにはなりません。) ■driver:Fileをdriver::Fileにしてみました。 ■driver:Fileをundefにしてみました。 ■my $query = new CGI;を追加し、 newの2番目の引数を$queryにしてみました。 ■tmpディレクトリの属性を744、766、777にしてみました。 ■/tmp を ./tmpにしてみました。 上記、いずれも同じ結果になってしまいました。 何がいけないのかわかりません。ファイルの構成は下記のようになっています。 /test.cgi /tmp /CGI/Session.pm /CGI/Session/ErrorHandler.pm アドバイスなどありましたら、よろしくお願いします。

  • perlにおけるセッションIDについて

    sessionIDがページを更新するたびに変わってしまいます。 その結果、前回セッションに保存した値を読み込めません。 my $cgi = new CGI; CGI::Session->name("SESSION_ID"); my $session = new CGI::Session("driver:File", $cgi, {Directory=>'./session'}); print $session->header(-charset=>'UTF-8'); print $session->id(); print $session->param("name"); #表示されず。 というようにしてセッションIDを表示すると、毎回変化します。 どうしたらIDを変わらないように出来るでしょうか? ちなみに、セッションに書き込むのは、 my $cgi = new CGI; CGI::Session->name("SESSION_ID"); my $session = new CGI::Session("driver:File", $cgi, {Directory=>'./session'}); $session->header(-charset=>'UTF-8'); $session->param("name", "abc"); $session->flush(); undef($session); こんな処理をしてます。

    • ベストアンサー
    • Perl
  • セッションがうまくできません

    #!c:/Perl/bin/Perl.exe ------セッションを作成する------- use CGI::Session; $session = new CGI::Session(undef,undef,{Directory=>'/tmp'}); $session->expire('+50s'); $session->param("membername","テスト"); $session->flush(); print "Location: ./test.pl\n\n"; ------セッションを読み込む------- #!c:/Perl/bin/Perl.exe print"Content-type: text/html\n\n"; use CGI; use CGI::Session; $q = new CGI(); $session = CGI::Session->new(undef,$q,{Directory=>'/tmp'}); $params = $session->param_hashref(); print$params->{"message"}; $session->flush(); 何もブラウザに表示がされません、どこが間違ってるのでしょうか?

  • セッションタイムアウトエラー

    いつも参考にしております。 セッションタイムアウトのエラー(???)で困ってます。 ご存知の方がいらっしゃいましたら、ご教授お願いします。 環境: OS :Windows 2009 Sever ActivePerl : V5.8.9 Webサーバ :IISv7.0 CGI::Session.pm:v4.41 DB :Oracle 10g 詳細は下記のようです。 1.ログイン成功したら、セッションを作成します。 CGI::Session->name( "SID" ); my $session = new CGI::Session( "driver:File", undef, {Directory => 'C:/Inetpub/wwwroot/xxx/tmp/session'} ); $session->expire( '+10h' ); ...省略 2.上記で作成されたセッションIDを画面に保持し、画面遷移する際に セッションIDの存在チェックを行う my $session = CGI::Session -> new( undef, $sid, {Directory => 'C:/Inetpub/wwwroot/xxx/tmp/session'} ); if($sid eq $session -> id) { // セッションID存在する // 次の画面遷移する // セッションタイムアウト再設定 $session->expire( '+10h' ); } else { // セッションID存在しない $session->close; $session->delete; // 作成されたセッションファイルを削除 // エラー画面表示 } 現象: セッションタイムアウトの設定時間に経ってないにもかかわらず たまたまセッションタイムエラーが発生します。 P.S エラーの原因が特定できず、困ってます。 以上、宜しくお願いいたします

    • 締切済み
    • CGI
  • ファイル一覧表示で、ディレクトリを非表示

    ディレクトリ内の画像ファイルの一覧を表示させたいです。 検索したところ、以下の物を発見しました。 #!/usr/bin/perl $filename=$ENV{QUERY_STRING}; $lookdir = "../../image/event/"; $mime{html}="text/html"; $mime{htm}="text/html"; $mime{txt}="text/plain"; $mime{jpg}="image/jpeg"; if($filename eq '') { print "Content-type: text/html\n\n"; print "<html><body>\n"; opendir(DIR,"../../image/event/"); while($dir=readdir(DIR)) { print "<a href=\"$lookdir$dir\">$dir</a><br>\n"; } closedir(DIR); print "</body></html>\n"; } else { $ext=$filename; $ext=~s/.*\.//g; if($mime{$ext} ne '') { print "Content-type: $mime{$ext}\n\n"; open(R,$filename); print <R>; close(R); } } これで、ほぼOKなのですが、"."や".."が表示されてしまってます。 これを消したいのですが、良い方法は無いでしょうか?

    • ベストアンサー
    • Perl
  • クッキー方式のユーザー認証でユーザー名を表示させるには

    クッキーとセッションIDを使用したユーザー認証を使用しています。 ユーザー名を各ページに表示したいと思っています。CGIの場合は$ENV{'REMOTE_USER'}と表示すればID名がしっかり表示されるのですが、SSIで呼び出してHTMLなどに表示しようとしても出来ません。 【使用した簡単なスクリプト】 -------------- id-viewer.cgi ----------- #!/usr/local/bin/perl print "Content-type: text/plain\n\n"; print "$ENV{'REMOTE_USER'}\n"; --------------------------------------- 表示させたいHTMLに <!--#exec cgi="id-viewer.cgi"--> と明記 しかし何にも表示されませんでした。ためしに基本認証で実験した場合にはHTMLでもしっかりと表示されました。 どうぞよろしくお願いいたします。

    • 締切済み
    • CGI
  • デコードフォームについて。

    以下のスクリプトについて質問があります。かなり多いのですが・・・ sub DecodeForm #返り値:Name=>Val のハッシュ(グロブ) #使用例:*form = EncodeForm(); print $form{name}; { my($encoding) = @_; my($method) = $ENV{'REQUEST_METHOD'}; local($query, @in, $key, $val); require 'jcode.pl' if $encoding; if ($method eq 'GET') { $query = $ENV{'QUERY_STRING'}; } elsif ($method eq 'POST') { read(STDIN, $query, $ENV{'CONTENT_LENGTH'}); } local(@query) = split(/&/, $query); foreach (@query) { tr/+/ /; ($key, $val) = split(/=/); # %HH形式を元の文字にデコードする。 $key =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/ge; $val =~ s/%([A-Fa-f0-9][A-Fa-f0-9])/pack("c", hex($1))/ge; $val =~ s/\r\n/\n/g; jcode'convert(*key, $encoding) if ($encoding); jcode'convert(*val, $encoding) if ($encoding); $in{$key} = $val; } return *in; } 多いので先頭から順に箇条書きにさせて頂きます。 ・Name=>Val の意味。(#以下がメモであることは分かっています) ・グロブとは何か ・*form = EncodeForm(); print $form{name}; の意味。(特に、先頭の*が分かりません) ・my $encoding という変数も見たことがあるのですが、my($encoding) と my $encoding はどう違うのか。 ・クエリとは何か ・jcode.pl とは、インストールしたPerlに標準でついているライブラリなのか?そうでないのならjcode.plとは何か? ・%HH形式とは何か ・\rの意味 ・jcode'convert の意味 ・*key の * の意味 ・*in の * の意味 多くて申し訳ないです。分かる方いらっしゃいましたご教授くださると幸いです。よろしくお願いします。

    • ベストアンサー
    • Perl