ASP.NET で 独自認証処理 を 実装 する 方法

0 件のコメント

フォーム認証でも、Windows認証でもなく、完全に独自の認証方法を行う場合、どのような実装を行うかのサンプルを掲載します。 シングルサインオン を実装するような ケース を想定した実装例です。 実装が web.config や Global.asax なので、ASP.NET MVC、WCF等で有効な実装方法になるハズです(試したのは ASP.NET MVC4 のみ)。

目次

ソースコード

概要

サービス へ アクセス したときの動作と、本記事の範囲外ですが前提となる動作を以下にあげます。

本記事範囲内のユースケース

  • 認証されている場合(誰からのアクセスか特定できる場合)
    その認証情報はあらかじめクッキーに保存してあるので、クッキー情報から HttpApplication.User に復元します。
  • 認証されていない場合(誰からのアクセスかわからない or 初回アクセスの場合)
    そのまま通過させ 匿名ユーザー として処理を続行します。
  • 匿名ユーザーでは許可されないアクセスの場合
    http://localhost:8080/Account/Login へリダイレクトします。

本記事範囲外のユースケース

  • ユーザーを認証する
    IDとパスワードでユーザーを認証し、認証したことをクライアントのクッキーに保存します。

"独自認証処理"と言いながら、実際はフォーム認証と同じことを行っています。 ただ、自前で実装しているので、拡張修正が独自に行えるかと思います。 修正が必要そうな部分を見極めて修正を行ってください。

web.config の設定

system.web/authentication 要素において、 mode="None" を指定します。 これにより、認証処理を行わない(=自前でどうにかする)という設定になります。 認証処理はこのあとの Global.asax の実装 で記載します。

web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <authentication mode="None">
    </authentication>
    <authorization>
      <deny users="?"/>
    </authorization>
  </system.web>
</configuration>

Global.asax の実装

ここでは「認証されている場合に特定されたユーザーを設定」「認証されていない場合に匿名ユーザーを設定」「承認されない場合にリダイレクト」の3つを実装します。 が、「認証されていない場合に匿名ユーザーを設定」は何も処理しなければ、匿名ユーザーになるので、実質的に実装が必要なのは2つです。

「認証されている場合に特定されたユーザーを設定」は、Application_AuthenticateRequest で行います。 クッキーから復元し、設定を行います。

「承認されない場合にリダイレクト」は、Application_EndRequest で行います。 このメソッドは、ASP.NET に対する要求処理の一番最後のイベントとして呼ばれます。 このタイミングだと、匿名ユーザーがアクセスできない場所にアクセスしたかどうか(401 Unauthorized)が分かるので、ここでリダイレクト処理を実装します。

Global.asax

namespace ServiceProvider1
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Http;
    using System.Web.Mvc;
    using System.Web.Routing;
    using System.Web.Security;
    using System.Security.Principal;

    public class MvcApplication : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {
            AreaRegistration.RegisterAllAreas();

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

        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            // 認証情報を格納した Cookie を取得
            var authCookie = this.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;
            }
        }

        protected void Application_EndRequest(object sender, EventArgs e)
        {
            var url = string.Empty;

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

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

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

おまけ

「リダイレクト先のサービス(http://localhost:8080)」と「本記事で作成したサービス」の web.config に 同じ machineKey を記載すると、シングルサインオン擬き が作れます。 machineKey の生成については こちら をご参照ください。 フォーム認証ページの作成方法については こちら(ASP.NET MVC + WebAPI)こちら(ASP.NET MVC) をご参照ください。

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!