if文がうまく書けない(T.T)

このQ&Aのポイント
  • 某CGIを改造してます。CGIにIDとPassを組み込もうとしているのですが、うまくできません。
  • sub pass2の書き方が間違っている可能性があります。正しい名前を入れても「名前が違います」のメッセージが出る問題があります。
  • 言語はperlです。
回答を見る
  • ベストアンサー

if文がうまく書けない(T.T)

某CGIを改造してます。 CGIにIDとPassを組み込もうとしているのですが、うまくできません。 いろいろな認証CGIを真似してやっているのですが… sub pass2{ open (FILE,"$passdata"); @file = <FILE>; close FILE; foreach (@file) { local($nm,$ps)= split(/,/,$_); if ($nm eq $in{'name'} && crypt($in{'password'},$ps) eq "$ps") { &admin; exit; } } &error("認証に失敗しました?"); } この状態だと動くことは動くのですが、ちょっと面倒なので逆転させたいんです。 そこで以下のように作り変えてみました。 if ($nm ne $in{'name'}) { &error("名前が違います"); exit; } if ($nm eq $in{'name'} && crypt($in{'password'},$ps) ne "$ps") { &error("パスワードが違います。"); exit; } } &admin } こうすると、なぜか正しい名前を入れても「名前が違います」のメッセージが出ます。 いったいどこが間違っているのですか? 言語はperlです。 お願いします。

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

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

  • ベストアンサー
回答No.4

#3です。 改造案を書いてみますので参考にしてみて下さい sub pass2{ open (FILE,"$passdata"); @file = <FILE>; close FILE; #名前が正しい場合1を代入する $nameFlg=0; foreach (@file) { local($nm,$ps)= split(/,/,$_); #名前が正しいかどうかを確認する if($nm eq $in{'name'}){ $nameFlg=1; } if ($nm eq $in{'name'} && crypt($in{'password'},$ps) eq "$ps") { &admin; exit; } } #名前だけあっている場合はパスワードが違うと表示する if($nameFlg=1){ &error("パスワードが違います"); }else{ &error("認証に失敗しました?"); } } 申し訳ないのですが、実際に動かしていないので すぐ動く保証はありません。 あしからず。

master-3rd
質問者

お礼

すばやい返答ありがとうございます。 早速試してみたいと思います。 余談ですが、 #1さんとの受け答えで返答した案についてはどのように思われますか? あの感じで間違ってはいないでしょうか?それとも、ほかに何か良い方法がありますか? 時間があるようだったら確認してください。 よろしくお願いします。

その他の回答 (3)

回答No.3

まず、ユーザ情報(名前とパスワード)が記録されている ファイル$passdataの構成を考えます。 名前 パスワード A氏 111 B君 222 C  333 上記のような形だと思うのですが、ここで、 改造後のソースに B君―222 というのを入れます。 すると以下のようになります。 まず入力された名前がファイルの一番目の名前と同じか 判定する(最初のif文 if ($nm ne $in{'name'}) の動き) すると、入力値はB君なので、エラーメッセージを出し、 終了してしまう。 となります。 バグの原因はここです。 入力された名前が何番目にあるのかはわかりませんから、 登録されている全員の名前と比べても一致しない場合に エラーを出さないといけないのに、違ったら 即座にエラーを出してしまっていることです。 改造前のソースはわかりやすいですし、かなり簡素に 書いていると思いますので、変更しないほうが 良いと思いますよ。

master-3rd
質問者

お礼

返答ありがとうございます。 なぜ動かないのかは理解できました。次をチェックするという機能がないということであっているでしょうか? また、確かに参考にした認証CGIはとてもわかりやすく、素人が見てもどういう風に処理がされているのかがよくわかるものでした。変更しないことがベストだとは思います。 ただ、1つほしい機能があるんです。 名前が間違っているのか、パスワードが間違っているか?を確認するというものです。 現状では、どちらかが間違っていても「認証失敗」と出すだけでどっちが間違っているか?というのは出ないですよね。 入力する人も一度入れてしまえばオートコンプリートを使うと思うのでそんなには間違えないとは思うのですが… 今の状態からCGIを大きく変化させることなく上記のことが可能ですか? 絶対必要な機能ではないので無理なら無理で問題はないのですが、簡素にできる方法があるようでしたら教えてください。 お願いします。

  • the845t
  • ベストアンサー率33% (246/743)
回答No.2

一応 たぶんだけど、sub error{}の方でexit;してるはずだから、 要らないと思う。 逆に、 &admin;の方では必要なのでは? ※あと&adminの後の「;」が抜けてますよ。

  • the845t
  • ベストアンサー率33% (246/743)
回答No.1

だって、 foreachで@fileの1行目から順番にやってるでしょ。 1行目に登録されている名前と、ログインしようとする名前が違うだけでそのエラーが出るよ。 そういう書き方してますよ。 何が面倒で書き直したのかわかりませんが、 名前が違う=認証に失敗しましたってことで前のヤツで良かったのでは?

master-3rd
質問者

お礼

返答ありがとうございます。 もともとのスクリプトにはPassだけの認証が付いていたのですが、それはすべてのサブルーチンの頭で認証しているんです。 多分、直接モードを選択されたときにはじくためだと思うのですが… 質問の修正前の書き方だとすべて新規入力画面に行ってしまい、修正・削除画面に行き着かなくなります。(sub delやsub editなど)これをそのまま生かそうとしたら各サブルーチンにこれを貼り付ける必要がありますよね。 その場合、「&admin」の部分にサブルーチンすべてが入ってしまう訳で… 方法として、メインを if ($mode eq "admin") { &admin; } if ($mode eq "edit1") { &admin; } if ($mode eq "del") { &admin; } 等にしておき、 if ($nm eq $in{'name'} && crypt($in{'password'},$ps) eq "$ps") { &admin; exit; } を if ($nm eq $in{'name'} && crypt($in{'password'},$ps) eq "$ps") { if ($mode eq "admin") { &admin; } if ($mode eq "edit1") { &edit1; } if ($mode eq "del") { &del; } exit; } とするほうがスマートなのでしょうか? ほかにもいい方法がありましたら教えてください。

関連するQ&A

  • if文が・・・??

    CGIの認証部分を改造中です。 修正画面に入るとき、各ユーザーのパスワードと管理人パスワードを設定し、ユーザーなら自分の記事の一部を管理人なら記事とユーザー名等の修正が出来るというものです。 さて、以下のように作りました。 if ($in{'pass1'} ne $pass || $in{'pass1'} ne "$adminpass"){&error("パスワードが違います.$pass.$in{'pass1'}.$adminpass.");} あ、後ろのほうは確認用です。 これだと、文法的に間違えはないとおもうのですが、エラーが帰ってきます。 もちろん、「$passと$in{'pass1'}」または「$in{'pass1'}と$adminpass」は同じです。 ちなみに、 if ($in{'pass1'} ne $pass){&error("パスワードが違います");} とすると、ちゃんと通るし、 if ($in{'pass1'} ne "$adminpass"){&error("パスワードが違います");} こっちでもちゃんと通ります。 もちろん、PASSはちゃんと変更してです。 これって何かおかしいですか? 出来れば、「ここはおかしくないよ」という回答もお待ちしてます。

    • ベストアンサー
    • Perl
  • IF文でページ振り分けがうまく出来てない。

    CGI勉強中です。 ある掲示板CGIを改造して会員のみに使用可にしようと考えています。パスワード自体は無事組み込むことが出来たのですが、1つ問題が出ました。 掲示板なので、過去ログがありますよね。その過去ログページを表示しようとするとまた認証ページに戻ってしまい、パスワードを再度入力→最新10件のページに戻ってしまいます。どうにかして、1度入ったらパスワードを入力しなくてもいいようにしたいのですが… 今のところこうなってます。 /////////////// if ($pass_mode == '1'){ ←もしパスを使用するだったら if ($F{'mode'} eq '') { &pass_mode} ←モード無しの場合、パス入力画面に移動 if ($F{'mode'} eq 'admin') { &admin} ←モードアドミニならsub adminへ } else{ if ($F{'mode'} eq '') { &main_form} ←メイン書き込みページへ else { &{$F{'mode'}} } } /////// となっています。 また、過去ページへの移動は「**.cgi?pg=10&sort=」という感じです。 この状態で、ページ移動時にパス入力ページに移動しないようにするにはどうしたらいいでしょうか?cookieを使う必要があったりしますか? 抜けてる情報・足りない情報があったら指摘してください。すぐ補足します。言語はperlで書いています。 よろしくお願いします。

    • ベストアンサー
    • CGI
  • if 文  わかんない・・・

    都道府県セレクトoptionフォームにて 都道府県を選択しない場合のエラーを なんとか2行で出せるようになったのですが 選択して下さい = value="0" if ($in{'pre'} eq '0') { &error("都道府県の選択!!"); } if ($in{'pre'} eq "") { &error("都道府県の選択!!"); } これを1行にするにはどうしたらいいのでしょう? ↓↓はダメでした(≧m≦) if ($in{'pre'} eq "" || '0') { &error("都道府県を選択!!"); }

    • ベストアンサー
    • Perl
  • CGIでパスワードのセキュリティについて

    CGIで管理者用パスワードを設定しますが(画面入力と比較するワード)、 このパスワードは インターネットからファイルをダウンロードするアプリ ケーションなどでソースを見られてしまう事は無いのでしょうか? もし見られてしまう場合 何か防ぐ方法は有りませんか? xxx.cgi?pass=pass1234 とかやれば良いでしょうか? # 管理用パスワード $pass = 'pass123'; ←これです パスワード <input type=password name=pwd size=8> if ( $in{'pwd'} ne $pass ) { &error("パスワードが違います"); } サーバーは ニフティ又はビックローブを予定。

    • ベストアンサー
    • CGI
  • phpのif文について

    phpでログイン処理のif文を書いています。 nameとpasswordのフィールドが記入されているのかをチェックするif文を書いたのですが、機能してくれません。何かが間違っているのでしょうか。 何も入力しないor間違った情報を入力する ということをしてもログインが出来てしまいます。 どなたかテェックお願い致します。 <?php require('dbconnect.php'); session_start(); if ($_COOKIE['name'] != '') { $_POST['name'] = $_COOKIE['name']; $_POST['password'] = $_COOKIE['password']; $_POST['save'] = 'on'; } if (!empty($_POST)) { // ログインの処理 if ($_POST['name'] != '' && $_POST['password'] != '') { $sql = sprintf('SELECT * FROM members WHERE name="%s" AND password="%s"', mysql_real_escape_string($_POST['name']), sha1(mysql_real_escape_string($_POST['password'])) ); $record = mysql_query($sql) or die(mysql_error()); if ($table = mysql_fetch_assoc($record)) { // ログイン成功 $_SESSION['id'] = $table['id']; $_SESSION['time'] = time(); // ログイン情報を記録する if ($_POST['save'] == 'on') { setcookie('name', $_POST['name'], time()+60*60*24*14); setcookie('password', $_POST['password'], time()+60*60*24*14); } header('Location: index.php'); exit(); } else { $error['login'] = 'failed'; } } else { $error['login'] = 'blank'; } } ?>

    • ベストアンサー
    • PHP
  • if文についてです

    アンケート入力の際、if文で5ヵ所のうちひとつでも空欄の場合「未記入です」と表示させたいのですが、下記のプログラミングでは半角数字でアンケート欄に入力すると上手くいくのですが日本語でアンケート欄に入力すると未記入のエラーがでます。原因はなぜなのでしょうか? (cgiファイルの一部分です) if($name == "" or $address == "" or $day == "" or $month == "" or $year == "" ){ $error1 ="未記入項目があります"; &Error; exit; } exit; sub Error{ print<<FORM; <html> <head> <title>空欄エラー</title> </head> <body> $error1 <form action="okweb.cgi"> <input type="submit" value="戻 る"> </form> </body> </html> FORM }

    • ベストアンサー
    • Perl
  • htmlからcgiに変数を配列にして渡すとき

    フォームにて、質問1,2,3…と入力してもらい、 1を答えないで2を答えるとか、 2を答えないで3を答えるとかを排除したいので、 変数を配列にして受け取りたいのです。 とりあえず今のところはこうなってます。↓ #htmlファイル# <INPUT type="text" size="30" name="situmon[1]"> <INPUT type="text" size="30" name="situmon[2]"> ... としてcgiに持っていき、 #cgiファイル# for($i=1; $i<=4; $i++){ if($form{'situmon[$i]'} eq "" && $form{'situmon[$i+1]'} ne ""){ &error; #→エラーメッセージサブルーチン exit; } } のようにして受け取ろうとしてるのですが、うまくいきません。 上のようにhtmlではどう書くべきか、cgiではどう受け取るべきかを教えてくだされば嬉しいです。

    • ベストアンサー
    • CGI
  • perl if文 助けて~

    perl初心者ながら暇見て住所CGIフォームを作っています。 だんだん完成してきましたが今一歩です(T_T)ご指導下さい! 名前、電話、都道府県、住所、の4つの項目があります。 {'nam'} {'tel'} {'pre'} {'add'} {'pre'}はSELECToption 他はtextFORM 全部記入した時には、次に進めてOKなのです。 if ((($in{'nam'}) && ($in{'tel'}) && ($in{'add'}) && ($in{'pre'} > "0")) { print 全部未記入時でも、次に進んでも無記入なのでOKです。 エラー時に&errorのエラー画面に飛ばす事も出来ました。 ただ、書き忘れ時が困るので {'nam'} {'tel'} {'pre'} {'add'}の内、1~3つとか記入して 他が抜けてたりした時だけエラーにしたいのです。 でも間違って空スペースとかでエラーが出て欲しくないし・・・ まずは下記でやってもまだダメです、($in{'pre'} > "0")が未選択時がダメです(T_T) 色々やってみたのですが、何か良い方法ありませんか? #### ($in{'pre'} > "0")は、"1"以上が「真」の条件です。 if ((($in{'nam'} eq "") || ($in{'tel'} eq "") || ($in{'add'} eq "")) && ($in{'pre'} > "0")) { &error("エラー"); }

    • ベストアンサー
    • Perl
  • 削除する記事が存在しない場合の処理

    投稿すると自動的にその投稿に対して記事番号なるものが割り当てられ、 その記事番号と自分で投稿時に決めた削除パスワードで 自分の投稿を削除する形式の掲示板なのですが パスワードや記事番号が入力されていない場合には 〇〇〇が入力されていませんと表示されるにもかかわらず 存在しない記事番号が入力して削除しようとすると 「正常に削除いたしました」と表示されてしまいます。 (実際には存在しない記事番号なので何も削除されていないのですが) そこで下記のようにの#~#の部分を追加で記述し、 記事番号が存在しない場合にエラーとなるようにしてみたのですが これで本当にいいのか正直不安なのです。 正しいかチェックしていただけませんか? @new=(); open (IN,"$file") || error("システムエラー","ファイル「$file」を開くことができません。"); while($data = <IN>) { $flag=0; ($no,$res,$date,$cntr,$email,$tall,$weight,$age,$sub,$com,$live,$select,$photo,$pw) = split(/<>/,$data); if ($FORM{'pass'} eq "$ad_pass") { foreach $del (@DEL) { if ($no eq "$del") { $flag=1; last; } } } else { if ($FORM{'del'} eq "$no") { if (!($pw)) { &error("入力エラー","指定された記事には削除キーが設定されていません。"); } if (crypt($FORM{'pass'},$pw) ne "$pw") { &error("入力エラー","パスワードが間違っています。"); } $flag=1; } #記事番号が存在しない時、エラーを表示追加 if ($FORM{'del'} ne "$no") { if (crypt($FORM{'pass'},$pw) ne "$pw") { &error("入力エラー","記事番号が存在しません。記事番号を確認して入力し直してください。"); } } #ここまで } if ($flag == 0) { push(@new,$data); } } close (IN);

    • ベストアンサー
    • Perl
  • vbs Do文がうまく機能しない?

    下記のコードを書いたのですが、うまく機能しません。 やりたいことは、ある読取りパスワードが設定されているエクセルファイルに、いくつかのパスワードを自動で適用して、パスワードが一致した時にエクセルファイルを開くということです。 実際にエクセルファイルに「password1」と設定して実行するとうまく開くのですが、「password2」を設定した場合、エクセルファイルは開かずに終わってしまいます。 私としては、Do文が絡んだときにPASSという変数にpassword2の文字列がうまく代入されていないのではないかと思っていますが、原因がわかりません。 何かご指摘を頂けると助かります。 ====================================================== Dim xlApp, PASS Dim x On Error Resume Next x = 1 Do until x = 10 Set xlApp=CreateObject("Excel.Application") If x = 1 Then PASS = "password1" If x = 2 Then PASS = "password2" xlApp.Workbooks.Open "D:\pass\test.xls", 0, False, 5, PASS If Err.Number = 0 Then xlApp.Visible = True Exit Sub End If xlApp.Workbooks.Close Set xlApp = Nothing x = x + 1 Loop On Error Goto 0 Set xlApp = Nothing ====================================================== よろしくお願いします。

専門家に質問してみよう