ブラウザのwindow間で情報(値)をやりとりする方法、特に「親->子」方向について。

ここ数日苦労したので記録することにした。



テストサイトはこちらからどうぞ。


【 発端編 】

業務用のwebアプリにおいては認証が非常に重要になる。
IDとパスワードをどう扱うかである。

今取り掛かっているシステムで直面している問題だった。



システムに入る場合、毎回パスワードを入れればいいのだろうが、そうも言っていられない。
多くの場合「cookie」でブラウザに記憶させるのだが、問題が起こる場合がある。
複数のユーザを一覧にしてをワンクリックで見たい場合である。
この場合は、今まではurlに書き込んでサーバーサイドで認証してhtmlを返していた。

この方法だとurlにパスワードが書き込まれてあまり好ましくないのである。



【 試行錯誤編 】


googleさんにお聞きした所、openerを使って、子ウインドウから親ウインドウに値を書き込むことは出来るようだった。確かに、この方法でhtmlを読んで付け加えて新しいWindowに書き込むことも出来るだろう。

document.open();->document.write("hogehoge");
で開いたウインドウに文字列を書き込むのは出来るようだったが、それでは過激なのである。
幾つかの文字列を新しいWindowの要素に書き込みたいのである。


そこで、親ウインドウから子ウインドウに書き込めるのかなあと思い探してみるが見つからない。



開いたウインドウの要素に値を親側からpushしたいのである。
サンプルを見ればわかるが、呼び出し元側には複数のリンクがある状態なので、なかなか難しい。



ブラウザの仕様として、「ウインドウを開く時」に新しいウインドウに渡せるのはWindow名だけである。

もちろんwindow名にすべて(idからパスワードまで)書き込むことは出来るのだが、長くなるので、あまり好ましくないような気がした。

今取り掛かっているシステムではパスワードが3種類あるのである(笑)。

そこで、開いたWindowの値を親側から変えられるか悩み続けた。
調査とテスト(試行錯誤)を重ねているうちに、催事なことに気がついた。
もし、誰かのパソコン上ですでに開いてあるWindowに値を他のWindowから変更できたら、まずいのである。セキュリテイ上の脅威である。

それで、親Windowから子どもWindowに文字列を書き込む方法は諦めがついた。




【 解決編 】

調べていくと、他のWindowに紐付けられているjavascriptの関数は呼べるということがわかった。
なので、
1)子どもWindowをdivのIDをWindow名にして開く
2-1)子どもWindowが開いてhtmlが読み込まれ終わった時に
2-2)Window名をパラメータにして親ウインドウの関数を呼ぶ

3-1)親の関数ではパラメータを元にdivを特定する
3-2)divをオブジェクトとして渡す。(ソースがシンプルになった)

4-1)子どものWindowでは受け取ったオブジェクトから必用な値を取り出す。


何とも書いてみると簡単で、短いソースなのだが、多分30時間位かかった。




【 補足と少し賢くなった編 】


ところが、相棒にテストを頼んで、ローカルに落としたソースを使って「ダブルクリックで動かしてテスト」してもらったら上手く動かないのである。

唖然である。僕の環境では上手く動いているのにである。

なおかつブラウザで異なる動きをした。
safari v6,firefox v35では動くのが、Chrome 40 とsafar v8では動かないのだった。
いずれも、サーバーにアップしたurlでは動くのであった。

Chromeのデバッガで見たら、セキュリティ上の問題と出ているのである。

Uncaught SecurityError: Blocked a frame with origin "null" from accessing a frame with origin "null". Protocols, domains, and ports must match.



誰かが、悪意あるhtmlを書いて、ターゲットのWindowのjavascriptを実行しようとした場合のセキュリテイであることに気がついた。
ターゲットのurl(port)と同じhtmからしか実行できないようにブラウザが制御しているのである。
ダブルクリックで開けると、違ったurl(port)に属していると判断するのであった。

これに気がついてよかったのである。
従来javascriptデバッグapacheを経由しないで行っていたためにそんなところにも気がついた。


少し賢くなった。

ブラウザは最新にしておかねばならないのだが、僕のmacは10.7.5なのでsafarはv8に出来ないようだった。
firefoxは最新でも、そうなっていないようだった。


僕の事例では、管理者は一旦自分のパスワードでログインするし、会員のパスワードは皆知っている。
そんな状況でしか開かない画面である。
その画面のソースを見ればパスワードもまるわかりなのだが、管理者認証を通っていなければこの画面にはこれない。
なので、このままでいいかと思う。




しかし、親のWindowから子どものWindowに値をpushする方法がわかってよかった。

今までだと、cookieでパスワードをcgiに渡してシステム名などを持ってきたが、これならば親ウインドウから持ってこれる。
ajaxでのやりとりが少し軽くなって嬉しい。



542981