ASP.NET の IHttpModule の 実装 と 利用

0 件のコメント

ASP.NET アプリケーション に対して モジュール化 された複雑な機能、処理を提供したい場合、 IHttpModule を利用すると便利です。 例えば、複数に分散してしまったアプリケーションに対して、ある決まった認証処理を実装させたいとき、簡単に機能を提供することが可能になります。 ここでは、認証されていないユーザーがアクセスしてきたとき、別のサイトへ転送させる機能を提供する HttpModule を作成します。

目次

概要

作成する HttpModule の機能は「認証されていないユーザーがアクセスしてきたとき、別のサイトへ転送させる機能」というものです。 以下は、上記機能提供する HttpModule の実態作成と、提供された HttpModule の利用方法 の 2部 構成になっています。

IHttpModule の 実装

IHttpModule インターフェース では、void Init(HttpApplication)void Dispose() を実装します。 基本的には HttpApplication の イベントハンドラ に処理を追加することで動作させます。

以下のサンプルコードでは AuthenticateRequestEndRequest の 2イベント を実装しています。 その他のイベント、イベント実行順は こちら にまとめてありますので、参考にしてください。

CustomHttpModule.cs

namespace MvcApplication.Modules
{
    using System;
    using System.Security.Principal;
    using System.Web;
    using System.Web.Security;

    public class CustomHttpModule : IHttpModule
    {
        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            context.AuthenticateRequest += new EventHandler(this.onAuthenticateRequest);
            context.EndRequest += new EventHandler(this.onEndRequest);
        }

        private void onAuthenticateRequest(object sender, EventArgs e)
        {
            var application = (HttpApplication)sender;

            // 認証情報を格納した Cookie を取得
            var authCookie = application.Request.Cookies[FormsAuthentication.FormsCookieName];

            // Cookie が 存在する場合
            if (authCookie != null && !string.IsNullOrEmpty(authCookie.Value))
            {
                // Cookie から 認証情報 を復元
                var ticket = FormsAuthentication.Decrypt(authCookie.Value);
                var identity = new GenericIdentity(ticket.Name, "Single Sing-On");
                var pricinpal = new GenericPrincipal(identity, new string[] { });
                HttpContext.Current.User = pricinpal;
            }
        }

        private void onEndRequest(object sender, EventArgs e)
        {
            var url = string.Empty;
            var application = (HttpApplication)sender;

            // 401:Unauthorized でない場合、何もしない
            if (application.Response.StatusCode != 401)
            {
                return;
            }

            // リダイレクト用の URL を生成
            url += "http://localhost:8080/Account/Login";
            url += "?ReturnUrl=";
            url += HttpUtility.UrlEncode(application.Request.Url.ToString());

            // リダイレクト
            application.Response.Redirect(url);
        }
    }
}

onAuthenticateRequest は「認証処理」なので、クッキー や セッション 、クエリパラメター等から アクセス してきた ユーザー を特定する処理を記述します。 ここで承認しょりまでは行いませんし、ましてやリダイレクト処理も記載しません。

onEndRequest はすべての処理が完了したとき呼ばれる処理です。 この段階で StatusCode が 401 のとき、初めて承認されなかったことがわかります。 承認されなかった場合、今回はリダイレクトさせるようなコーディングを行っています。

もし仮に onAuthenticateRequest において リダイレクト処理 を記載した場合、「一部のページは未認証でも利用できるようにする」ことができなくなります(未認証だと無条件でリダイレクトされてしまうため)。 これを利用できるようにするためには、上記のような実装が必要になります。

IHttpModule の 利用

実装した IHttpModule 実態クラス の利用は、 web.config へ記載で行います。 今回作成した IHttpModule の完全修飾名は MvcApplication.Modules.CustomHttpModule なので、この名前を type に記載します。

web.config(ASP.NET MVC3)

<configuration>
  <system.web>
    <httpModules>
      <add name="CustomHttpModule" type="MvcApplication.Modules.CustomHttpModule" />
    </httpModules>
  </system.web>
</configuration>

web.config(ASP.NET MVC5)

<configuration>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="CustomHttpModule" type="MvcApplication.Modules.CustomHttpModule"/>
    </modules>
  </system.webServer>
</configuration>