質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

2155閲覧

サイトへの自動ログインが最初の数回は成功し、以降は失敗する原因について

risaito74

総合スコア44

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2017/01/11 13:30

編集2017/01/12 00:45

PHP

1 2<?php 3$homepage = file_get_contents('とあるサイトのURL'); 4 5preg_match('/PHPSESSID\" value=\"(\w+)/', $homepage, $match); 6$phpsessid = $match[1]; 7 8preg_match_all('/hidden\" value=\"(\w+)/', $homepage, $match); 9$hidden1 = $match[1][0]; 10$hidden2 = $match[1][1]; 11$hidden3 = $match[1][2]; 12$bot_check = $match[1][3]; 13 14//***** POST ***** 15$url = 'とあるサイトのURL'; 16$data = array( 17 'username' => 'ユーザー名', 18 'password' => 'パスワード', 19 'login' => "ログイン", 20 'PHPSESSID' => $phpsessid, 21 $hidden1 => $hidden1, 22 $hidden2 => $hidden2, 23 $hidden3 => $hidden3, 24 'bot_check' => $bot_check, 25); 26 27$headers = array( 28 'Content-Type: application/x-www-form-urlencoded', 29); 30 31$options = array('http' => array( 32 'method' => 'POST', 33 'content' => http_build_query($data), 34 'header' => implode("\r\n", $headers), 35)); 36$contents = file_get_contents($url, false, stream_context_create($options)); 37echo $contents;

上記のPHPでとあるサイトへ自動ログインする処理を作りました。
最初の数回は無事ログインでき、ログイン後のhtmlが$contentsに返ってきましたが、その後はログイン後のhtmlが取得できなくなりました。
($homepageにはログイン画面のhtmlが問題なく取得できており、またPOSTする各要素も問題ないことを確認しています)
この場合、どのような原因が考えられるでしょうか?
よろしくお願い致します。

追記:
ご指摘ありがとうございます。その後の調べた状況ですが、
「さくらインターネット」上では最初の数回成功した後は、ずっと失敗(ログイン後のhtmlが取得できない)が続いています。
また、別の環境でも試しているのですが、こちらは成功したり失敗したりという状況ですので、「実行しているサーバ環境」と「ログインしたいサービス側のサーバの状況(重さ?)」の問題ではないか…と推測しています。
以上、現状報告です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

popobot

2017/01/11 23:38

一度失敗してから、成功したことはあるのでしょうか
risaito74

2017/01/12 00:46

ご指摘ありがとうございます。追記させていただきました。上記の通り実行環境によって挙動が異なるので、サーバ依存の問題なのだろうか…と現状は考えています。
popobot

2017/01/12 01:03

いくつか回答がついたので深追いはしませんが、環境やタイミングによって発生するならtimeoutとかが起きているのではないかとちょっと思いました。
guest

回答3

0

ベストアンサー

具体的な回答ではありませんが、、

PHPコードの先頭に以下2行を追加し、どのようなエラーメッセージが表示されるか確認してみてください。

php

1ini_set('display_errors',1); 2error_reporting(E_ALL);

また、file_get_contents()の直後に以下の1行を追加し、どのようなレスポンスヘッダが返却されているのかも確認してみてください。

php

1var_dump($http_response_header);

http://php.net/manual/ja/reserved.variables.httpresponseheader.php

最後に、質問文の

その後は取得できなくなりました。

について、
「何が取得されるのか」
あるいは
「どのような現象が発生するのか」
を具体的に記載すると、回答が付きやすくなると思います。

追記

完全に当てずっぽうの回答となりますが、
レスポンスヘッダーにConnection: closeとあり、サーバ側からTCP接続の切断を通知されていることから、
icchii様のコメントのように timeout が発生しているか、サーバ側に"不正アクセス"と見なされているのではないかと推測します。

"timeout"については、アクセスに成功する場合と失敗する場合それぞれでレスポンスが返って来るまでの時間を計測してみてください。
また、アクセスの頻度を落としたり、しばらく時間をあけてから再度、試してみたりすると、状況が変わるかも知れません。

"不正アクセス"については、リクエストヘッダーに"Content-Length"フィールドと"User-Agent"フィールドを追加してみてください。

HTTPの仕様によると、メッセージボディを含むリクエストには"Content-Length"ヘッダーフィールドが必須のようです。
https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4

For compatibility with HTTP/1.0 applications, HTTP/1.1 requests containing a message-body MUST include a valid Content-Length header field unless the server is known to be HTTP/1.1 compliant.

リクエストヘッダーに"Content-Length"フィールドを追加する方法は、以下などが参考になるかと思います。
http://php.net/manual/ja/function.file-get-contents.php#102575

また、"User-Agent"フィールドが設定されていない場合、何らかのセキュリティ機構によって"不正アクセス"とみなされる可能性は高くなると思います。
PHP は、デフォルトの設定では"User-Agent"フィールドを設定しません。
http://php.net/manual/ja/filesystem.configuration.php

名前 デフォルト 変更可能 変更履歴

user_agent NULL PHP_INI_ALL PHP 4.3.0 から利用可能です。

他にも必要なリクエストヘッダーがあるかも知れませんので、HTTPや"とあるサイト"の仕様などを調べてみてください。

投稿2017/01/11 14:27

編集2017/01/12 03:29
KiyoshiMotoki

総合スコア4791

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

risaito74

2017/01/11 14:35

ご指摘ありがとうございます。 先頭に2行追加しましたが、特にエラー出力などはありませんでした。 var_dumpは以下の通りです。 array(6) { [0]=&gt; string(15) "HTTP/1.1 200 OK" [1]=&gt; string(35) "Date: Wed, 11 Jan 2017 14:30:42 GMT" [2]=&gt; string(14) "Server: Apache" [3]=&gt; string(17) "Content-Length: 0" [4]=&gt; string(17) "Connection: close" [5]=&gt; string(39) "Content-Type: text/html; charset=EUC-JP" } 「取得できる/できない」ですが、ログイン後の画面のhtmlを「取得できる」状態を成功、そのhtmlが返ってこない状態(null?空文字?)を「取得できない」=失敗と表現していました。
KiyoshiMotoki

2017/01/12 03:30

情報の追記、ありがとうございます。 回答欄に追記させていただきましたので、確認してみてください。 あと、コメント欄に記載いただいた情報は質問欄にも追記しておくことをお勧めします。 その方が多くの人の目に留まりやすいため、さらに回答を得やすくなると思いますので。
risaito74

2017/01/12 09:33

ご丁寧にご助言いろいろとありがとうございます。いくつか検証すべき項目、正しく理解すべき事柄が見えてきましたので、一度本件はクローズにさせていただきます。大変ありがとうございました。
guest

0

一般的にPHPSESSIDって一時的なセッションidでしょうから、
先方のサーバーで失効されたら意味なくなりますよね。

基本的にログイン(サインイン)するたびにPHPSESSIDって一時的に生成されるものでしょうから、
ログイン後にPHPSESSIDを取得して保持するように仕組みの見直しが必要ではないかと。

投稿2017/01/12 00:25

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

risaito74

2017/01/12 00:50

ありがとうございます。手動でログインするとログイン後のhtmlにPHPSESSIDがありますので、この「ログイン後のPHPSESSIDを入手すること」がプログラムの目的になっていますが、htmlから取得する以外の方法もあるだろうと思いますので、勉強しながら見直しを検討してみたいと思います。
risaito74

2017/01/12 09:36

はい、cURLの理解、導入検討もしてみます。ありがとうございます。
guest

0

「取得できる/できない」ですが、ログイン後の画面のhtmlを「取得できる」状態を成功、そのhtmlが返ってこない状態(null?空文字?)を「取得できない」=失敗と表現していました。

以下のようにignore_errorsを追加してください。
file_get_contents()でURLにアクセスした際、httpステータスが200以外の場合もコンテンツを取得するようになります。(「取得できない」=失敗 の原因がわかります。)

php

1$options = array('http' => array( 2 'method' => 'POST', 3 'content' => http_build_query($data), 4 'header' => implode("\r\n", $headers), 5 'ignore_errors' => true, 6)); 7

投稿2017/01/12 00:40

Y.H.

総合スコア7914

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

risaito74

2017/01/12 09:39

ありがとうございます。こちらも試してみたいと思います。様々な情報、ご助言を皆様からいただきましたので、一度クローズして各種検証をすすめてみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問