カスタムメンバーシップユーザーの実装


カスタムメンバーシッププロバイダを使用してMembershipUserクラスを拡張する方法を示す例を示します.
ユーザSystem.Web.Profileは、各ユーザの情報をWebアプリケーションに格納するための便利なメカニズムを提供するが、アプリケーションの設計は、ユーザ認証情報および他のユーザ情報をMembershipデータ記憶領域に格納することを要求する場合がある.この場合、ユーザー認証情報およびその他のユーザー値をデータ記憶領域に格納および取得するためにカスタムメンバーシッププロバイダを生成する必要があります(カスタムメンバーシッププロバイダの例については、メンバーシッププロバイダの実装を参照).さらに、MembershipUserクラスを拡張して、追加したユーザ値をアプリケーションコードに使用できるようにすることもできます.
カスタムメンバーシップユーザーの作成には、次のタスクが含まれます.
MembershipUserクラスを継承するクラスを作成します.
認証情報と他のユーザー設定を格納するデータ・ソースを作成します.
データ・ストレージにカスタム・メンバーシップ・プロバイダを作成します.このカスタムメンバーシッププロバイダには、カスタムメンバーシップユーザータイプのオブジェクトを入力として使用し、カスタムメンバーシップユーザータイプのオブジェクトを返す他のコードが含まれます.
このトピックの例では、方法:メンバーシッププロバイダの実装のプレゼンテーションのカスタムメンバーシッププロバイダの例を変更して、カスタムメンバーシップユーザーの実装をサポートする方法を示します.
カスタムメンバーシップユーザーの作成
MembershipUserクラスを継承するクラスを作成し、他のユーザー値を公開するプロパティを含むカスタムメンバーシップユーザーを作成できます.さらに、MembershipUserクラスにメソッドおよびイベントを追加することもできる.
Membershipクラスを呼び出してカスタムMembershipUserのインスタンスを作成すると、MembershipUserクラスによって定義されたコンストラクタのみが呼び出されます.MembershipUserが他のコンストラクション関数を含むリロードを実装する場合、これらのコンストラクション関数は、カスタムコンストラクション関数を呼び出すために特別に作成されたアプリケーションコードによってのみ呼び出されます.
次のコード例では、MembershipUserクラスを継承する単純なカスタムメンバーシップユーザーを示し、2つの他のプロパティを提供します.IsSubscriberとCustomerIDです.前者はブールプロパティで、ユーザーがWebアプリケーションにサービスまたはニュース原稿を購読するかどうかを識別します.後者には、個別の顧客データベースの一意の識別子が含まれます.
using System;
using System.Web.Security;

namespace Samples.AspNet.Membership.CS
{
    public class OdbcMembershipUser : MembershipUser
    {
        private bool _IsSubscriber;
        private string _CustomerID;

        public bool IsSubscriber
        {
            get { return _IsSubscriber; }
            set { _IsSubscriber = value; }
        }

        public string CustomerID
        {
            get { return _CustomerID; }
            set { _CustomerID = value; }
        }

        public OdbcMembershipUser(string providername,
                                  string username,
                                  object providerUserKey,
                                  string email,
                                  string passwordQuestion,
                                  string comment,
                                  bool isApproved,
                                  bool isLockedOut,
                                  DateTime creationDate,
                                  DateTime lastLoginDate,
                                  DateTime lastActivityDate,
                                  DateTime lastPasswordChangedDate,
                                  DateTime lastLockedOutDate,
                                  bool isSubscriber,
                                  string customerID) :
                                  base(providername,
                                       username,
                                       providerUserKey,
                                       email,
                                       passwordQuestion,
                                       comment,
                                       isApproved,
                                       isLockedOut,
                                       creationDate,
                                       lastLoginDate,
                                       lastActivityDate,
                                       lastPasswordChangedDate,
                                       lastLockedOutDate)
        {
            this.IsSubscriber = isSubscriber;
            this.CustomerID = customerID;
        }



    }
}

CreateUserWizardのコントロールを変更してメンバーシップユーザの他のユーザ情報を含める例については、方法:ASPをカスタマイズする.NET CreateUserWizardコントロールを参照してください.
メンバーシップ・ユーザー・データのデータ・ストレージの作成
メンバーシップ機能のユーザー認証情報と、カスタムメンバーシップユーザーの他のユーザー情報にデータストレージ領域を指定する必要があります.
次のコード例では、Microsoft Accessデータベースでクエリーを実行して、カスタムメンバーシップユーザーの認証情報と属性値を格納するテーブルを作成できるクエリーを示します.
CREATE TABLE Users
(
  PKID Guid NOT NULL PRIMARY KEY,
  Username Text (255) NOT NULL,
  ApplicationName Text (255) NOT NULL,
  Email Text (128) NOT NULL,
  Comment Text (255),
  Password Text (128) NOT NULL,
  PasswordQuestion Text (255),
  PasswordAnswer Text (255),
  IsApproved YesNo, 
  LastActivityDate DateTime,
  LastLoginDate DateTime,
  LastPasswordChangedDate DateTime,
  CreationDate DateTime, 
  IsOnLine YesNo,
  IsLockedOut YesNo,
  LastLockedOutDate DateTime,
  FailedPasswordAttemptCount Integer,
  FailedPasswordAttemptWindowStart DateTime,
  FailedPasswordAnswerAttemptCount Integer,
  FailedPasswordAnswerAttemptWindowStart DateTime,
  IsSubscriber YesNo,
  CustomerID Text (64)
)

カスタムメンバーシッププロバイダの作成
カスタムメンバーシップ・ユーザー・タイプとカスタムメンバーシップ・データ・ストレージ領域をサポートするカスタムメンバーシップ・プロバイダを作成する必要があります.カスタムメンバーシッププロバイダのGetUserメソッドおよびCreateUserメソッドを記述して、カスタムメンバーシップユーザータイプのオブジェクトを返すことができます.カスタムメンバーシッププロバイダのUpdateUserメソッドを記述して、カスタムメンバーシップユーザタイプのオブジェクトを入力として使用できます.
次のセクションでは、カスタムメンバーシップユーザータイプを使用するカスタムメンバーシッププロバイダの作成に関するガイドを示します.例は、方法:メンバーシッププロバイダの実装のプレゼンテーションで提供されたコードに基づいて、このトピックの前のメンバーシップ・ユーザー・データのデータ・ソースの作成で提供されたデータベース・アーキテクチャを使用します.

GetUserメソッドの変更


カスタムメンバーシップ・ユーザー・タイプを使用する場合、メンバーシップ・プロバイダのMembershipProvider..::..GetUserメソッドとMembershipProvider..::..GetUserメソッドは、MembershipUserタイプのオブジェクトを返す必要があります.カスタムメンバーシップユーザクラスがMembershipUserクラスを継承すると、GetUserメソッドを実装する戻り値としてカスタムメンバーシップユーザタイプのオブジェクトが返されます.次に、アプリケーションコードは、次のコード例に示すように、カスタムメンバーシップユーザの他のメンバーにアクセスするために、返されたMembershipUserをカスタムメンバーシップユーザタイプとして強制的に変換することができる.
次のコード例では、方法:メンバーシッププロバイダの実装のプレゼンテーションのメンバーシッププロバイダの変更後のGetUserメソッド(およびプライベートメソッドのサポート)の例を示します.これらのメソッドは、このトピックの前のカスタムメンバーシップユーザーの作成セクションのカスタムメンバーシップユーザータイプを返すために更新されました.
//
// MembershipProvider.GetUser(string, bool)
//

public override MembershipUser GetUser(string username, bool userIsOnline)
{
   OdbcConnection conn = new OdbcConnection(connectionString);
   OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion," +
        " Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
        " LastActivityDate, LastPasswordChangedDate, LastLockedOutDate," +
        " IsSubscriber, CustomerID" +
        " FROM Users  WHERE Username = ? AND ApplicationName = ?", conn);

  cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
  cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName;

  OdbcMembershipUser u = null;
  OdbcDataReader reader = null;

  try
  {
    conn.Open();

    reader = cmd.ExecuteReader();

    if (reader.HasRows)
    {
      reader.Read();
      u = GetUserFromReader(reader);

      if (userIsOnline)
      {
        OdbcCommand updateCmd = new OdbcCommand("UPDATE Users  " +
                  "SET LastActivityDate = ? " +
                  "WHERE Username = ? AND Applicationname = ?", conn);

        updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTime.Now;
        updateCmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
        updateCmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName;

        updateCmd.ExecuteNonQuery();
      }
    }

  }
  catch (OdbcException e)
  {
    if (WriteExceptionsToEventLog)
    {
      WriteToEventLog(e, "GetUser(String, Boolean)");

      throw new ProviderException(exceptionMessage);
    }
    else
    {
      throw e;
    }
  }
  finally
  {
    if (reader != null) { reader.Close(); }

    conn.Close();
  }

  return u;      
}


//
// MembershipProvider.GetUser(object, bool)
//

public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
  OdbcConnection conn = new OdbcConnection(connectionString);
  OdbcCommand cmd = new OdbcCommand("SELECT PKID, Username, Email, PasswordQuestion," +
        " Comment, IsApproved, IsLockedOut, CreationDate, LastLoginDate," +
        " LastActivityDate, LastPasswordChangedDate, LastLockedOutDate," +
        " IsSubscriber" +
        " FROM Users  WHERE PKID = ?", conn);

  cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey;

  OdbcMembershipUser u = null;
  OdbcDataReader reader = null;

  try
  {
    conn.Open();

    reader = cmd.ExecuteReader();

    if (reader.HasRows)
    {
      reader.Read();
      u = GetUserFromReader(reader);

      if (userIsOnline)
      {
        OdbcCommand updateCmd = new OdbcCommand("UPDATE Users  " +
                  "SET LastActivityDate = ? " +
                  "WHERE PKID = ?", conn);

        updateCmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = DateTime.Now;
        updateCmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey;

        updateCmd.ExecuteNonQuery();
      }
    }

  }
  catch (OdbcException e)
  {
    if (WriteExceptionsToEventLog)
    {
      WriteToEventLog(e, "GetUser(Object, Boolean)");

      throw new ProviderException(exceptionMessage);
    }
    else
    {
      throw e;
    }
  }
  finally
  {
    if (reader != null) { reader.Close(); }

    conn.Close();
  }

  return u;      
}


//
// GetUserFromReader
//    A helper function that takes the current row from the OdbcDataReader
// and hydrates a MembershipUser from the values. Called by the 
// MembershipUser.GetUser implementation.
//

private OdbcMembershipUser GetUserFromReader(OdbcDataReader reader)
{
  object providerUserKey = reader.GetValue(0);
  string username = reader.GetString(1);
  string email = reader.GetString(2);

  string passwordQuestion = "";
  if (reader.GetValue(3) != DBNull.Value)
    passwordQuestion = reader.GetString(3);

  string comment = "";
  if (reader.GetValue(4) != DBNull.Value)
    comment = reader.GetString(4);

  bool isApproved = reader.GetBoolean(5);
  bool isLockedOut = reader.GetBoolean(6);
  DateTime creationDate = reader.GetDateTime(7);

  DateTime lastLoginDate = new DateTime();
  if (reader.GetValue(8) != DBNull.Value)
    lastLoginDate = reader.GetDateTime(8);

  DateTime lastActivityDate = reader.GetDateTime(9);
  DateTime lastPasswordChangedDate = reader.GetDateTime(10);

  DateTime lastLockedOutDate = new DateTime();
  if (reader.GetValue(11) != DBNull.Value)
    lastLockedOutDate = reader.GetDateTime(11);

  bool isSubscriber = false;
  if (reader.GetValue(12) != DBNull.Value)
    isSubscriber = reader.GetBoolean(12);

  string customerID = String.Empty;
  if (reader.GetValue(13) != DBNull.Value)
    customerID = reader.GetString(13);        

  OdbcMembershipUser u = new OdbcMembershipUser(this.Name,
                                        username,
                                        providerUserKey,
                                        email,
                                        passwordQuestion,
                                        comment,
                                        isApproved,
                                        isLockedOut,
                                        creationDate,
                                        lastLoginDate,
                                        lastActivityDate,
                                        lastPasswordChangedDate,
                                        lastLockedOutDate,
                                        isSubscriber,
                                        customerID);

  return u;
}
 

UpdateUserメソッドの変更


カスタムメンバーシップユーザタイプおよびカスタムメンバーシッププロバイダを使用する場合、UpdateUserタイプのオブジェクトを入力として使用するMembershipUserメソッドが実装される.UpdateUserメソッドの実装では、提供されたMembershipUserオブジェクトは、他の属性の値にアクセスし、データ記憶領域で更新するために、カスタムメンバーシップユーザタイプに強制的に変換される.
次のコード例は、提供されたユーザを、このトピックの前の方法:メンバーシッププロバイダの実装のプレゼンテーションセクションのカスタムメンバーシップユーザタイプに強制的に変換するために更新されたUpdateUserのメンバーシッププロバイダの変更後のカスタムメンバーシップユーザーの作成の方法の例を示す.
public override void UpdateUser(MembershipUser user)
{
  OdbcConnection conn = new OdbcConnection(connectionString);
  OdbcCommand cmd = new OdbcCommand("UPDATE Users " +
          " SET Email = ?, Comment = ?," +
          " IsApproved = ?, IsSubscriber = ?, CustomerID = ?" +
          " WHERE Username = ? AND ApplicationName = ?", conn);

  OdbcMembershipUser u = (OdbcMembershipUser)user;

  cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = user.Email;
  cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = user.Comment;
  cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = user.IsApproved;
  cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = u.IsSubscriber;
  cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = u.CustomerID;
  cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = user.UserName;
  cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName;


  try
  {
    conn.Open();

    cmd.ExecuteNonQuery();
  }
  catch (OdbcException e)
  {
    if (WriteExceptionsToEventLog)
    {
      WriteToEventLog(e, "UpdateUser");

      throw new ProviderException(exceptionMessage);
    }
    else
    {
      throw e;
    }
  }
  finally
  {
    conn.Close();
  }
}
 

CreateUserメソッドの変更


カスタムメンバーシップ・ユーザー・タイプとカスタムメンバーシップ・プロバイダを使用する場合、CreateUserクラスでサポートされている属性のみを入力として使用するMembershipUserメソッドを実装する必要があります.次のコード例に示すように、他の属性値を用いたCreateUserメソッドのリロードを作成できます.
ただし、MembershipクラスまたはMembershipクラスに依存するコントロール(CreateUserWizardコントロールなど)は、このリロードを呼び出すことはありません.このメソッドをアプリケーションから呼び出すには、Membershipクラスで参照されているMembershipProviderインスタンスをカスタムメンバーシッププロバイダタイプに強制的に変換し、CreateUserリロードを直接呼び出します.
アプリケーションがCreateUserWizardコントロールを使用してメンバーシップデータソースに新しいユーザーを追加する場合は、CreateUserWizardコントロールのウィザードステップをカスタマイズして、カスタムメンバーシップユーザーの他の属性値を取得するコントロールを含めることができます.次に、CreateUserWizardコントロールのCreatedUserイベントを処理し、次の操作を実行するイベントコードを追加できます.
他のメンバーシップ・ユーザーの属性値を取得します.
CreateUserWizardコントロールで作成されたメンバーシップユーザーを、カスタムメンバーシップユーザータイプに強制的に変換します.
メンバーシップユーザーのその他のプロパティを設定します.
更新されたユーザをMembershipクラスのUpdateUserメソッドに渡す.これにより、カスタムプロバイダのUpdateUserメソッド(このトピックの前のUpdateUserメソッドの変更セクションで説明した)が呼び出され、データ・ソースに他の属性値が追加されます.
説明
 
CreateUserWizardステップを変更する例については、方法:ASPをカスタマイズする.NET CreateUserWizardコントロールを参照してください.
次のコード例は、このトピックの前の方法:メンバーシッププロバイダの実装のプレゼンテーションセクションのカスタムメンバーシップユーザタイプを返すために更新されたCreateUserのメンバーシッププロバイダの変更後のカスタムメンバーシップユーザーの作成メソッドの例を示す.カスタムメンバーシッププロバイダの他のプロパティの値を入力として使用するために、リロードが作成されました.
public override MembershipUser CreateUser(string username,
           string password,
           string email,
           string passwordQuestion,
           string passwordAnswer,
           bool isApproved,
           object providerUserKey,
           out MembershipCreateStatus status)
{
  return this.CreateUser(username, password, email,
                        passwordQuestion, passwordAnswer,
                        isApproved, providerUserKey, false, "",
                        out status);
}


//
// OdbcMembershipProvider.CreateUser -- returns OdbcMembershipUser
//

public OdbcMembershipUser CreateUser(
         string username,
         string password,
         string email,
         string passwordQuestion,
         string passwordAnswer,
         bool isApproved,
         object providerUserKey,
         bool isSubscriber,
         string customerID,
         out MembershipCreateStatus status)
{
  ValidatePasswordEventArgs args = 
    new ValidatePasswordEventArgs(username, password, true);

  OnValidatingPassword(args);

  if (args.Cancel)
  {
    status = MembershipCreateStatus.InvalidPassword;
    return null;
  }

  if (RequiresUniqueEmail && GetUserNameByEmail(email) != "")
  {
    status = MembershipCreateStatus.DuplicateEmail;
    return null;
  }

  MembershipUser u = GetUser(username, false);

  if (u == null)
  {
    DateTime createDate = DateTime.Now;

    if (providerUserKey == null)
    {
      providerUserKey = Guid.NewGuid();
    }
    else
    {
      if ( !(providerUserKey is Guid) )
      {
        status = MembershipCreateStatus.InvalidProviderUserKey;
        return null;
      }
    }

    OdbcConnection conn = new OdbcConnection(connectionString);
    OdbcCommand cmd = new OdbcCommand("INSERT INTO Users " +
          " (PKID, Username, Password, Email, PasswordQuestion, " +
          " PasswordAnswer, IsApproved," +
          " Comment, CreationDate, LastPasswordChangedDate, LastActivityDate," +
          " ApplicationName, IsLockedOut, LastLockedOutDate," +
          " FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, " +
          " FailedPasswordAnswerAttemptCount, FailedPasswordAnswerAttemptWindowStart, " +
          " IsSubscriber, CustomerID)" +
          " Values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", conn);

    cmd.Parameters.Add("@PKID", OdbcType.UniqueIdentifier).Value = providerUserKey;
    cmd.Parameters.Add("@Username", OdbcType.VarChar, 255).Value = username;
    cmd.Parameters.Add("@Password", OdbcType.VarChar, 255).Value = EncodePassword(password);
    cmd.Parameters.Add("@Email", OdbcType.VarChar, 128).Value = email;
    cmd.Parameters.Add("@PasswordQuestion", OdbcType.VarChar, 255).Value = passwordQuestion;
    cmd.Parameters.Add("@PasswordAnswer", OdbcType.VarChar, 255).Value = EncodePassword(passwordAnswer);
    cmd.Parameters.Add("@IsApproved", OdbcType.Bit).Value = isApproved;
    cmd.Parameters.Add("@Comment", OdbcType.VarChar, 255).Value = "";
    cmd.Parameters.Add("@CreationDate", OdbcType.DateTime).Value = createDate;
    cmd.Parameters.Add("@LastPasswordChangedDate", OdbcType.DateTime).Value = createDate;
    cmd.Parameters.Add("@LastActivityDate", OdbcType.DateTime).Value = createDate;
    cmd.Parameters.Add("@ApplicationName", OdbcType.VarChar, 255).Value = pApplicationName;
    cmd.Parameters.Add("@IsLockedOut", OdbcType.Bit).Value = false;
    cmd.Parameters.Add("@LastLockedOutDate", OdbcType.DateTime).Value = createDate;
    cmd.Parameters.Add("@FailedPasswordAttemptCount", OdbcType.Int).Value = 0;
    cmd.Parameters.Add("@FailedPasswordAttemptWindowStart", OdbcType.DateTime).Value = createDate;
    cmd.Parameters.Add("@FailedPasswordAnswerAttemptCount", OdbcType.Int).Value = 0;
    cmd.Parameters.Add("@FailedPasswordAnswerAttemptWindowStart", OdbcType.DateTime).Value = createDate;
    cmd.Parameters.Add("@IsSubscriber", OdbcType.Bit).Value = isSubscriber;
    cmd.Parameters.Add("@CustomerID", OdbcType.VarChar, 128).Value = customerID;

    try
    {
      conn.Open();

      int recAdded = cmd.ExecuteNonQuery();

      if (recAdded > 0)
      {
        status = MembershipCreateStatus.Success;
      }
      else
      {
        status = MembershipCreateStatus.UserRejected;
      }
    }
    catch (OdbcException e)
    {
      if (WriteExceptionsToEventLog)
      {
        WriteToEventLog(e, "CreateUser");
      }

      status = MembershipCreateStatus.ProviderError;
    }
    finally
    {
      conn.Close();
    }


    return (OdbcMembershipUser)GetUser(username, false);      
  }        
  else
  {
    status = MembershipCreateStatus.DuplicateUserName;
  }


  return null;
}