フォーム認証でも、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 の フォロー」 お願いします!!