none
IIS 7.5+ASP.NETのフォーム認証Webサイトに特定のUser-Agentでアクセスすると401.2発生 RRS feed

  • 質問

  • IIS 7.5+ASP.NETで動作するフォーム認証を設定したWebサイトに対し、ログインしてからでないとアクセスできないページにアクセスしたとき、要求ヘッダのUser-Agentのが特定の値(主に携帯電話のユーザーエージェント)だとログイン用のページにリダイレクトせず401.2エラーとなるケースを確認しました。たとえばtelnetでUser-Agentに次の値を指定すると再現します(これはNTTドコモ様が提供するiモードシミュレータIIの値です):

    DoCoMo/2.0 ISIM60(c500;TB;W24H16)

    回避策を模索していますが、まだうまい手が見つかりません。アドバイス等いただければたいへんありがたく存じます。
    2011年1月11日 5:07

回答

  • マネージパイプラインモードに「クラシック」を指定したアプリケーションプールを指定すると発生しないことを確認しました。
    • 回答としてマーク 山本春海 2011年1月31日 7:52
    2011年1月21日 1:47

すべての返信

  • 回避すればいいのでしょうか? もっと言うと挙げられているシミュレータ上でのみ動作すればいいのでしょうか? 実機でも動作することが目的なのではと思いますが…。

    ASP.NETではUser-Agentを元にブラウザの持つ機能を把握し、その機能範囲内で動作する ようになっています。ASP.NETのバージョンにもよりますが、2.0~3.5であれば

    C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers\docomo.browser

    にその情報があり、このファイルの一番下に使用されているシミュレータも定義されています。これを読むとcookiesもsupportsRedirectWithCookieもtrueなのでエラーになっている原因はちょっとわかりません。問題はシミュレータ以外のもっと古い機種だとこれらのオプションもfalseなことです。ログイン以外にもいろいろと問題が出るように思います。

    • 回答の候補に設定 山本春海 2011年1月31日 7:52
    2011年1月12日 22:12
  • コメントありがとうございます。

    もちろん根本的に解決したいのですが、手がかりが少ないため対策のターゲットも定められない状態です。最終的な目的は実機での動作です。

     

    ASP.NETブラウザ登録ツール(aspnet_regbrowsers.exe)でランタイム ブラウザ機能アセンブリをグローバル アセンブリ キャッシュからアンインストールしても状況は変わりません。

    http://msdn.microsoft.com/ja-jp/library/ms229858%28v=vs.80%29.aspx

     

    cookieは利用しませんし、古い機種は対象外とすることもできるので普通に動けばなんとかできるのですが、入り口で引っかかってしまっています。

    2011年1月13日 0:22
  • マネージパイプラインモードに「クラシック」を指定したアプリケーションプールを指定すると発生しないことを確認しました。
    • 回答としてマーク 山本春海 2011年1月31日 7:52
    2011年1月21日 1:47
  • マネージパイプラインモードに「クラシック」を指定したアプリケーションプールを指定すると発生しないことを確認しました。
    私も同様の現象が発生していまして、この記事も参考にさせていただいています。

    マネージ パイプライン モードを「クラシック」にすると、ASP.NETの「.NET の承認規則」による Authorize が行われない場合がありました。
    おそらく、行われなかったから、401.2エラーも発生しなかったのはないかと思います。
    IISの「承認規則」は未検証です。


    そこで、PostAuthenticateRequest イベント時に以下のように、自分でリダイレクト処理を書いて、実機でもエミュレータでも回避できました。

    if (!Context.SkipAuthorization)
    {
    	bool isAuthrised = UrlAuthorizationModule.CheckUrlAccessForPrincipal(Request.Path, Context.User, Request.HttpMethod);
    	if (!isAuthrised)
    	{
    		FormsAuthentication.RedirectToLoginPage();
    		Response.End();
    	}
    }
    
    

    Response.End()がないと、次の AuthoriseRequest 系のイベントに突入して、401.2エラーが発生しました。

    ASP.NETの「.NET の承認規則」は、
    system.web/authorization
    IISの「承認規則」は、
    system.webServer/security/authorization
    の設定という意味です。

    影響はないと思いますが、すべてのファイルをフォーム認証で保護するために、
    system.webServer/modules の runAllManagedModulesForAllRequests 属性を true にして、FormsAuthentication を再定義しています。

    昨日書いたばかりの未リリースのコードなので、何か間違いがあったらすみません。
    2011年2月2日 15:59
  • コメントありがとうございます。参考になりました。

    下記URLのイベント発生順序を見ますとPostAuthenticateRequestイベント以後のイベントが問題になっているということなんでしょうかね。

     

    http://note.miyabis.jp/article/33503965.html


    2011年2月4日 5:08
  • 「.NET の承認規則」は、UrlAuthorizationModule.OnEnter メソッドで実現しているようで、OnEnter はAuthorizeRequest イベントに紐づけられています。

    このメソッドの中で、条件が揃えば、Response.StatusCode = 401 を設定しています。

     

    その後、EndRequest イベントに紐付けっれたフォーム認証のFormsAuthenticationModule.OnLeave メソッドで、401だった場合は設定した LoginUrl にResponse.Redirect するようです。

     

    Redirect メソッドで302に書き換わることで、万事うまくいくはずでしたが、結果的にどこかうまくいかない理由は、わかりませんでした。


    ですので、AuthenticateRequest が終わって、Context.User が割り当てられた後で、かつ、AuthorizeRequest が始まる前、というのが処理するのが相応しいイベントではないかと思いました。

    実際のところは 401で終わらなければ良いので、処理しても良いタイミングはもっと幅広いです。

    2011年2月4日 6:43