【F# + ASP.NET MVC】 承認フィルターによるログイン認証を行うには

◆ ログイン認証プロバイダー

namespace Sample.Authorize

// #r "System.Web.ApplicationServices"
// #r "System.Configuration"
open System
open System.Web.Security

type CustomMembershipProvider() = 
    inherit MembershipProvider()

    override val Name = "customMembershipProvider" with get

    override x.ValidateUser(username : string, password : string) =
        // ユーザー名とパスワードが一致したら認証OKとする。
        username.Equals(password)

    override x.GetPassword(username, answer) =
        raise <| new NotImplementedException()
    
    // 省略(以下 override は、同様に NotImplementedException を実装
    // ・・・

◆ ロール プロバイダー

namespace Sample.Authorize

// #r "System.Web.ApplicationServices"
// #r "System.Configuration"
open System
open System.Web.Security

type CustomRoleProvider() = 
    inherit RoleProvider()

    override val Name = "customRoleProvider" with get

    override x.GetRolesForUser(username) =
        // ユーザー名が admin であれば管理者とする。
        if username.Equals("admin") then
            [|"Administrators"|]
        else
            [|"Gests"|]

    override x.GetUsersInRole(roleName) =
        raise <| new NotImplementedException()

    // 省略(以下 override は、同様に NotImplementedException を実装
    // ・・・

◆ Web.config

<?xml version="1.0"?>
<configuration>
  <!-- 省略 -->
  <system.web>
    <!-- フォーム認証(認証エラー時の遷移先) -->
    <authentication mode="Forms">
      <forms loginUrl="~/Login/Index" timeout="2880" />      
    </authentication>
    <!-- ログイン認証プロバイダー -->
    <membership defaultProvider="customMembershipProvider">
      <providers>
        <clear/>
        <add name="customMembershipProvider"
             type="Sample.Authorize.CustomMembershipProvider" />
      </providers>
    </membership>
    <!-- ロール プロバイダー -->
    <roleManager enabled="true" defaultProvider="customRoleProvider">
      <providers>
        <clear/>
        <add name="customRoleProvider"
             type="Sample.Authorize.CustomRoleProvider" />
      </providers>
    </roleManager>
  </system.web>
  <!-- 省略 -->
</configuration>

◆ Entity

namespace Sample.Entities

type Employee() = 
    member val Username = "" with get, set
    member val Password = "" with get, set

◆ ログイン用Controller

namespace Sample.Controllers

open System
open System.Web.Mvc
open System.Web.Security

open Sample.Entities
open Sample.Authorize

type LoginController() =
    inherit Controller()

    // ログイン認証プロバイダー
    member val Provider = new CustomMembershipProvider() with get, set
    
    member this.Index() =
        FormsAuthentication.SignOut()
        this.View() :> ActionResult

    [<HttpPost>]
    member this.Index(entity:Employee) =
        // ログイン認証
        if this.Provider.ValidateUser(entity.Username, entity.Password) then
            // 認証OK
            // 認証情報をURLへ保持
            FormsAuthentication.SetAuthCookie(entity.Username, false)
            // HOME画面へ遷移
            base.RedirectToAction("Index", "Home") :> ActionResult
        else
            // 認証NG
            this.ViewData.["Message"] <- "認証NG"             
            this.View(entity) :> ActionResult

◆ ログイン用View

@model Sample.Entities.Employee

@{ Layout = null; }

<!DOCTYPE html>
<html>
<head>
    <title>F# + ASP.NET</title>
</head>
<body>
    <div>
        @using (Html.BeginForm()) {
            <fieldset>
                <legend>User</legend>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Username)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Username)
                </div>
                <div class="editor-label">
                    @Html.LabelFor(model => model.Password)
                </div>
                <div class="editor-field">
                    @Html.EditorFor(model => model.Password)
                </div>
                <p>
                    <input type="submit" value="Login" />
                </p>
            </fieldset>
        }
    </div>
    <div>
        @ViewData["Message"]
    </div>
</body>
</html>

◆承認フィルターを実装したController(HomeController)

namespace Sample.Controllers

open System.Web
open System.Web.Mvc

type HomeController() =
    inherit Controller()
    
    // 認証フィルター(ロールが administrators の場合のみアクション可能)
    [<Authorize(Roles = "administrators")>] 
    member this.Index() =
        this.ViewData.["Message"] <- "Hello World!"
        this.View() :> ActionResult

◆認証時に表示するView(HomeView)

@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <div>
        @ViewData["Message"]
    </div>
</body>
</html>

コメントを残す

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

WordPress.com ロゴ

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

Twitter 画像

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

Facebook の写真

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

Google+ フォト

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

%s と連携中