DOBON.NET DOBON.NETプログラミング掲示板過去ログ

WebBrowserでアクセス制限

環境/言語:[.NET Frameword 4.0, C#]
分類:[.NET]

現在System.Windows.Forms.WebBrowserを拡張して
ホワイトリストによるアクセス制限が可能なFilterableWebBrowserを作成してい
ます。

機能としては下記のものを考えています。
1. ホワイトリストにドメイン名を指定する。
2. リストに含まれないページを開こうとするとそれを中断し、予め指定した別
のページへ移動させる。
3. リストに含まれるページ内であれば、リストに含まれないページも表示す
る。(広告のFrameなど。その広告をクリックした際は2が起動する)

実際にコードを組んで動作を確認しているのですが、Frameが存在するページで
思うように動作しません。
開こうとしているページが同ページ内であるかを
WebBrowserNavigatingEventArgs.TargetFrameName で判断していますが、
この部分が正しくないようで、同ページ内でも値が""である場面があります。

以下コードです。
----------------------------------------------------------------
/// <summary>
/// アクセス制限が可能なWebBrowserコントロール
/// </summary>
class FilterableWebBrowser : WebBrowser
{
/// <summary>
/// ホワイトリスト
/// </summary>
public list<string> WhiteList { get; private set; }
/// <summary>
/// コンストラクタ
/// </summary>
public FilterableWebBrowser()
: base()
{
// ホワイトリスト
this.WhiteList = new List<string>();
this.WhiteList.Add("www.hoge.co.jp");
// イベント
base.Navigating += this.OnNavigating;
}
/// <summary>
/// ページを開く前に発生
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void OnNavigating(object sender, WebBrowserNavigatingEventArgs e)
{
// ページが別ページで、ホワイトリストに含まれない
if ((e.TargetFrameName == "") &&
(!this.WhiteList.Contains(e.Url.DnsSafeHost))
{
// 制限
e.Cancel = true;
base.Navigate("hoge.html");
}
}
}
----------------------------------------------------------------
開くページが別ページであることを判断するのに
WebBrowserNavigatingEventArgs.TargetFrameName は相応しくないのでしょうか。
ほかに適切な案がありましたらご教授いただけると幸いです。
■No32304に返信(YURIさんの記事)

> 実際にコードを組んで動作を確認しているのですが、Frameが存在するページで
> 思うように動作しません。

思うように動作をしないというのは、どのように動作しているのでしょうか?


> 開こうとしているページが同ページ内であるかを
> 〜略〜
> 開くページが別ページであることを判断するのに

これらの意味がよく分かりません。
「開こうとしているページが同【サイト】(同ドメイン)内であるか」という意味でしょうか?
ページがページ内???
開くページが別ページなのは当たり前???

この辺の説明が具体的でないと、具体的な案は出せない気がします。


> WebBrowserNavigatingEventArgs.TargetFrameName で判断していますが、
> この部分が正しくないようで、同ページ内でも値が""である場面があります。

TargetFrameName はあくまでフレームのName(ある種のID)だと思います。
読み込んだページがフレーム形式で
<frame src="abcde.html" name="xxx">
のように定義されている場合「xxx」という値が取得できますが、
これはあくまでフレームを切り分けている訳であって、
対象のフレームのHTMLとフレーム内に表示するHTMLが別サイトであることも
可能だと思います。
また、フレームのNameは後からターゲットとしての利用が考えられているため、
ターゲットとして利用しない場合は空もありえるので、
これで判断するのはあまり意味が無いのかと思います。
(一般的にフレーム内に別サイトのページ表示するのはマナー的にはどうかとは思いますが、
 出来るか出来ないかでいうと出来てしまうので・・・)


> 以下コードです。

提示したコードを実行してみましたが,
(「)」が少ない等の誤記っぽいものはありましたが、それはさておき)
判定NG時の
> base.Navigate("hoge.html");
の実行で再度イベントが発生し、永久ループになりました。
この辺が「思うように動作をしない」という事なのでしょうか?
■No32305に返信(anさんの記事)
反応ありがとうございます。


>> 開こうとしているページが同ページ内であるかを
>> 〜略〜
>> 開くページが別ページであることを判断するのに
>
> これらの意味がよく分かりません。
> 「開こうとしているページが同【サイト】(同ドメイン)内であるか」という
意味でしょうか?
> ページがページ内???
> 開くページが別ページなのは当たり前???
>
> この辺の説明が具体的でないと、具体的な案は出せない気がします。
説明がわかりづらくて申し訳ありません。
ページの構成を用意しましたので、改めて説明させていただきます。

ページ「A」と、ページ「B」、ページ「C」が存在して、
Bは直接表示するパターン(以下B-1)と、Aに内包されるパターン(以下B-2)が
あります。

ホワイトリストにはAとCのドメイン名が指定されていて、
WebBrowserがAを開いた時はA,B-2を読み込み、B-1を開いた時はフィルタリング
を行いCへ移動・読み込みます。

このときB-1とB-2のNavigateイベントを判別したいのですが、その方法がわから
なかったため今回の質問をさせていただきました。


an様の解説によるとTargetFrameNameは今回の判別に適さないとのことですが、
WebBrowserはどのような情報からB-1とB-2の処理を判断しているのでしょうか?



> 提示したコードを実行してみましたが,
> (「)」が少ない等の誤記っぽいものはありましたが、それはさておき)
> 判定NG時の
>> base.Navigate("hoge.html");
> の実行で再度イベントが発生し、永久ループになりました。
> この辺が「思うように動作をしない」という事なのでしょうか?
大変失礼致しました。
元のコードから必要かと思われる部分を抜き出しましたが、誤りがあったようです。

base.Navigate("hoge.html") は
base.Navigate("http://www.hoge.co.jp/hoge.html") でした。
この修正を行うとホワイトリストに適応され、ループが発生しないのではないか
と思います。
添付ファイル: normal.png (13 KB)
■No32312に返信(YURIさんの記事)
> ページの構成を用意しましたので、改めて説明させていただきます。
大体理解しました。
ちなみに図的にFrameというよりIFrameに見えますがどちらでしょう?
処理に違いがあるのかは分かりませんがこの際はっきりさせといたほうが良いかと。


まずはじめに、当初言っていた
>>> WebBrowserNavigatingEventArgs.TargetFrameName で判断していますが、
>>> この部分が正しくないようで、同ページ内でも値が""である場面があります。
は、
<frame src="abcde.html" name="">
このようなFrameタグのName属性が空の時に発生しているという事であっているのでしょうか?

あっている事を前提に以下を書きます。


> an様の解説によるとTargetFrameNameは今回の判別に適さないとのことですが、
> WebBrowserはどのような情報からB-1とB-2の処理を判断しているのでしょうか?

WebBrowserとしてはB-1とB-2の判断はどちらもBを表示するのであって
Aを表示した時に
<frame src="http://別サイト/b.html">
となっているからフレーム内にBを表示していて
A内のリンクでは
<a href="http://別サイト/b.html" target="_top">
とかになっているからフレームを解除した状態のところにBを表示しているだけではないでしょうか?
=WebBrowserとしてはB-1とB-2の判断をする必要性がないように思えます。
(ある意味Frameの初期値とAタグの_topターゲットで判断になる?)

それを踏まえて

> このときB-1とB-2のNavigateイベントを判別したいのですが、その方法がわから
> なかったため今回の質問をさせていただきました。

とありますが、Navigateイベント(Navigating?)でしたい理由はなんなのでしょうか?
とりあえず、OnNavigatingの引数では判断できる材料はなさそうに思います。
WebBrowserコントロールについては詳しくないので、
代案の提示およびOnNavigatingの引数では判断できるかどうかは断定はできませんが・・・。

それでも、もし今現状のOnNavigatingでの処理で行くなら
・FrameタグのNameを必ず入れる。
・そもそも他サイト内容をFrame内でも表示するのはNGとする。
・一旦全部読み込んで読み込み完了時(DocumentComplete)に解析する。(解析方法はDOM?)
・NavigatingとDocumentCompleteで複合的に使ってうまくやる(イベントの発生具合が分からないので適当案です・・・)
くらいしか自分には考えられません。
(暇が無くて試していませんので本当にできるかは不明です。)

あとは少し観点が変わりますが、
> !this.WhiteList.Contains(e.Url.DnsSafeHost)
この条件を完全一致でなくて後方一致にするとか?
WhiteListに登録するのは
>this.WhiteList.Add("www.hoge.co.jp");
ではなく
>this.WhiteList.Add(".hoge.co.jp");
にして、「www.hoge.co.jp」はもちろん、「ads.hoge.co.jp」もOKにしてみたり。


# 個人的な考えですが、Frame経由では表示可能で、
# 直接では表示できないというのが、なんかすっきりしません。
# Frame経由なら何でも表示出来てしまうのであれば、
# フィルターとしての役割が薄れそうな気がするので。
# (Webサイト側からそのような条件があるのは分からんでもないのですが・・・)




ここからは本件とはあまり関係ありませんが、少し気になったので。

> 大変失礼致しました。
> 元のコードから必要かと思われる部分を抜き出しましたが、誤りがあったようです。
> 
> base.Navigate("hoge.html") は
> base.Navigate("http://www.hoge.co.jp/hoge.html") でした。
> この修正を行うとホワイトリストに適応され、ループが発生しないのではないか
> と思います。

「発生しないのではないかと思います。」
とはどういう事でしょうか?
「発生しない」
と断定できない理由があるのでしょうか?

DOBON.NET | プログラミング道 | プログラミング掲示板