仕事で、とあるサイトに接続する必要があった。
一般的なサイトではなく、仕事上の機密情報を扱うサイトだ。
サイト管理者から渡された「証明書」をインストールしていないとアクセスできないし、セキュリティを固めるために、いろいろな細工が施してある。
ActiveX を使用しているので、IE でしかアクセスできない。
必要だからアクセスしたいのに、なぜか Windows7 + IE9 でアクセスできない。
証明書の確認までは行くのだが、その後「Internet Explorer ではこのページは表示できません」となる。
とりあえず、非常用のノートPC で XP + IE8 でアクセスできたが、いろいろと不便。
Windows7 + Chrome で試すと、アクセスできる。
もっとも、アクセス後 ActiveX が使えないので何もできない。
しかし、証明書のインストールに失敗しているわけではなさそうだ、ということは確認できる。
IETester を入れてみて、IE7 でアクセスしたがやっぱりダメ。
FireFox + IETab2 、というのも試してみたが、これは単に IE9 を Tab 内で開いているだけなので当然ダメ。
いったい、何が原因で動かないのか。
とりあえずアクセスできる chrome と、IE9 の違いはどこにあるのか。
chrome で Javaコンソールを開き、アクセスして、ネットとのやり取りしたデータを覗く。
IE9 で開発者ツールを開き、アクセスして、ネットとのやり取りしたデータを覗く。
…比較して、違いに気がついた。
chrome では、認証フォームの内容を POST すると、HTTP ステータス 302 が帰ってきてリダイレクトして、次のアクセスは GET になっている。
IE9 では、同様にリダイレクトして、次のアクセスは POST 、しかも「中断」と表示されて実際のアクセスが行われていない。
何でこんなことになるんだ? と、HTTP の仕様を確認してみる。
もし 302 ステータスコードが GET や HEAD 以外のリクエストのレスポンスとして受信されたら、リクエストが発行された時点の条件から変わっているかもしれないため、ユーザエージェントはユーザに確認されなければ、リクエストを自動的にリダイレクトしてはならない。
…POST アクセスから、302 でリダイレクトしちゃいけないんだ。恥ずかしながら、知らなかった。
しかも、
注: RFC 1945 や RFC 2068 では、クライアントはリダイレクトするリクエストのメソッドを変えてはならないと明確に述べられている。
POST でアクセスされたのに、リダイレクトで GET に変えちゃいけないんだ。これも恥ずかしながら、知らなかった。
参考までに、僕は恥ずかしながら知らなかったが、2006年ごろからこの手の問題を指摘している人はいたようだ。
古くて新しい問題なんだな。
というわけで、わかったのは、「サイトのつくりが悪い」ということ。
アクセスできないのが当然の作り方をしているのだ。
IE9 が悪いのではなかった。濡れ衣だ。ごめんよ。
IETester も、「見た目」を確認するためのツールなので、HTTP アクセスは OS 標準(今回は IE9)のプログラムを使用しているのだろう。
とはいっても、現実問題として 302 のときは GET に切り替えてアクセス、というブラウザがほとんどで、正しく仕様に従ったのは IE9 が初めて、ともいえる。
実のところ、302 でなく、303 を返せばいいらしい。
この場合は、GET でリダイレクトされなくてはならない、と決まっているから。
ただし、ブラウザが HTTP 1.1 を理解できないと、303 は使えない。
…いまどき、1.0 のブラウザなんて無いでしょ?
2014.6.12 追記:
HTTP/1.1 の新仕様である RFC7230~7239 が作成されました。
POST 302 からの GET リダイレクトは、「それが可能なように実装されているブラウザがあまりにも多い」ことから、違反ではなくなりました。
ここに書いてある情報は古くなりましたが、日記なのでそのまま残しておきます。
…それにしても、また後出しで「IE は標準と違う」ことにされるのは、マイクロソフトがちょっとかわいそう。
翻って、自分の仕事の話。
PHP で作っているプログラムで、Location なんてしょっちゅう送っている。
そして、PHP では Location を送出すると、暗黙のうちにステータスコード 302 を返す。
…これ、問題あるね。PHP の仕様がバグっている、ということだ。
もっとも、ステータスコードは指定できるので、直前が POST のときは、明示的に 303 にしなくては。
ただし、303 と 302 は意味が違うので、単に POST アクセスからリダイレクトしたい、と言う理由で使うのは間違い。
ちゃんと意味を理解して使わないと。
HTTP 1.1 が前提であれば、307 というのもある。
こちらだと、POST アクセスの次は、POST で返してくれるそうである。
ただし、この場合も「自動的にリダイレクトしてはならない」という、302 と同じ制約は付く。
同じテーマの日記(最近の一覧)
関連ページ
別年同日の日記
申し訳ありませんが、現在意見投稿をできない状態にしています。 |