静的コンテンツにも SSL を強制する

以前に Windows Azure Web サイトで SSL を強制するというエントリを書きましたが、
この方法は ASP.NET MVC でハンドルされる HTTP 要求に対してのみ有効でした。
今回は、HTML/CSS/JS ファイルあるいはテキスト ファイルといった静的コンテンツに対しても、
SSL での通信を強制する方法について考えてみます。

 

まず、既定の状態では、
静的コンテンツに対する HTTP 要求は IIS 側での処理で完結してしまい、ASP.NET 側には到達しません。
ASP.NET MVC 5 の Web.config の HTTP ハンドラーの設定では、
拡張子のない HTTP 要求は ASP.NET で処理されるように構成されていますが、
拡張子の付いた HTTP 要求についてはとくに指定されていません。

そこで次のように、すべての HTTP 要求を ASP.NET で処理するように構成します。
すべてのパス (path="*") に対する HTTP ハンドラーとして System.Web.StaticFileHandler を指定します。


<configuration>
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
      <add name="Custom-StaticFileHandler" path="*" verb="GET" type="System.Web.StaticFileHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
</configuration>


 

次に、HTTP でアクセスされた場合のフィルタリングについてです。
ASP.NET MVC で処理される場合はカスタム フィルター属性を利用できますが、
StaticFileHandler では当然それを利用できません。

そこで、HTTP 要求の最初に発生するイベントである HttpApplication.BeginRequest イベントを利用します。
Global.asax.cs で、次のようにイベント ハンドラーを追加します。


using System;
using System.Configuration;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;

namespace HandlersMvc
{
    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }

        void Application_BeginRequest(object sender, EventArgs e)
        {
            if (!Request.IsSecureConnection)
            {
                var url = Request.Url.AbsoluteUri;
                var secureUrl = Regex.Replace(url, @"^\w+(?=://)", Uri.UriSchemeHttps);

                if (PermanentHttps)
                {
                    Response.RedirectPermanent(secureUrl, true);
                }
                else
                {
                    Response.Redirect(secureUrl, true);
                }
            }
        }

        static bool PermanentHttps
        {
            get { return Convert.ToBoolean(ConfigurationManager.AppSettings["app:PermanentHttps"]); }
        }
    }
}


プロトコルが HTTPS でない場合は、HTTPS の URL にリダイレクトさせます。
これで、静的コンテンツも含め、すべての HTTP 要求に対して SSL を強制できるようになりました。

HTML/CSS/JS ファイル

テキスト ファイル

Web.config などのファイルにはアクセスできません。

構成ファイル

 

なお、今回の例では、
永続的なリダイレクト (301) か一時的なリダイレクト (302) かを Web.config で指定できるようにしています。


<configuration>
  <appSettings>
    <add key="app:PermanentHttps" value="false" />
  </appSettings>
</configuration>


Azure Web サイトでは、管理ポータルの [構成] で設定値をオーバーライドすることもできます。

Azure Web サイトの構成

永続的なリダイレクト (301)

 

バージョン情報
.NET Framework 4.5
ASP.NET MVC 5

参照
HTTPS および SSL による Windows Azure Web サイト (WAWS) のセキュリティ保護
ハンドラー <handlers> (TechNet)
Windows Azure Web サイトで SSL を強制する
静的コンテンツへの要求を動的に処理する

コメント / トラックバック2件 to “静的コンテンツにも SSL を強制する”

  1. 静的コンテンツへの要求を動的に処理する | Do Design Space Says:

    […] 前回の静的コンテンツにも SSL を強制するの投稿に関連して、 .txt などの静的コンテンツの拡張子を持った HTTP 要求を動的に処理する方法について書きます。 […]

  2. Windows Azure Web サイトで SSL を強制する | Do Design Space Says:

    […] (追記: この投稿の強化版として、静的コンテンツにも SSL を強制するという投稿を追加しました。) […]


コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。