WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

Windows Forms アプリで Membership を利用

by WebSurfer 11. February 2014 17:47

ASP.NET の Membership オブジェクトと Roles オブジェクトを Windows Forms アプリケーションでも利用できるという話です。

Windows Forms アプリで Membership と Roles を利用

Membership オブジェクトおよび Roles オブジェクトは、ASP.NET が web.config の情報を基に Membership プロバイダおよび Role プロバイダ(ユーザー情報のストアが SQL Server の場合は SqlMembershipProvider および SqlRoleProvider)を利用して自動的に生成します。

プログラマがコードを書いて Membership オブジェクト、Roles オブジェクトを作る手段は提供されていません。なので、ASP.NET Web アプリケーションでしか使用できないと思っていましたが、実はそうではなかったです。(汗)

そのことは、MSDN フォーラムで Using the ASP.Net membership provider in a Windows forms application part 1. という記事を紹介されて、初めて知りました。

その記事によると、Windows コンソールアプリでも(ASP.NET でなくても)、app.config から(web.config からでなくても)設定値を取得して、Membership オブジェクトや Roles オブジェクトを自動的に生成してくれるということでした。

自分でも、以下のコードの Windows Forms アプリを作って試してみましたが、確かにその通りであることが確認できました。上の画像が以下のコードを実行したときのものです。

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web.Security;

namespace ASPNETMembershipWindowsForms
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
            
      this.listBox2.DataSource = Roles.GetAllRoles();

      List<string> userNames = new List<string>();
      foreach (MembershipUser user in Membership.GetAllUsers())
      {
        userNames.Add(user.UserName);
      }
      this.listBox1.DataSource = userNames;
    }

    private void button1_Click(object sender, EventArgs e)
    {
      if (Membership.ValidateUser(this.textBox1.Text, 
            this.textBox2.Text))
      {
        this.label3.Text = "Result: User validated.";
      }
      else
      {
        this.label3.Text = "Result: User invalid!";
      }            
    }

    private void button2_Click(object sender, EventArgs e)
    {
      if (this.listBox1.SelectedItem == null)
      {
        this.label6.Text = "Please select a user.";
        return;
      }

      if (this.listBox2.SelectedItem == null)
      {
        this.label6.Text = "Please select a role.";
        return;
      }

      string user = this.listBox1.SelectedItem.ToString();
      string role = this.listBox2.SelectedItem.ToString();

      try
      {
        if (Roles.IsUserInRole(user, role))
        {
          this.label6.Text = "Yes";
        }
        else
        {
          this.label6.Text = "No";
        }
      }
      catch (Exception ex)
      {
        this.label6.Text = ex.Message;
      }
    }
  }
}

app.config

<?xml version="1.0"?>
<configuration>
  <configSections>
  </configSections>
  <connectionStrings>
    <add name="MemberShip" 
      connectionString="..." 
      providerName="System.Data.SqlClient"/>
  </connectionStrings>

  <system.web>
    <machineKey validationKey="..." 
      decryptionKey="..." 
      validation="SHA1" 
      decryption="AES"/>

    <membership defaultProvider="SqlProvider">
      <providers>
        <remove name="SqlProvider"/>
        <add name="SqlProvider" 
          type="System.Web.Security.SqlMembershipProvider" 
          connectionStringName="MemberShip" 
          applicationName="MyHomePage" 
          enablePasswordRetrieval="false" 
          enablePasswordReset="true" 
          requiresQuestionAndAnswer="true" 
          requiresUniqueEmail="false" 
          passwordFormat="Hashed" 
          maxInvalidPasswordAttempts="5" 
          minRequiredPasswordLength="7" 
          minRequiredNonalphanumericCharacters="0" 
          passwordAttemptWindow="10"/>
      </providers>
    </membership>
        
    <roleManager enabled="true" defaultProvider="RoleProvider">
      <providers>
        <clear/>
        <add name="RoleProvider" 
          type="System.Web.Security.SqlRoleProvider" 
          connectionStringName="MemberShip" 
          applicationName="MyHomePage"/>
      </providers>
    </roleManager>
  </system.web>
  <startup>
    <supportedRuntime version="v2.0.50727"/>
  </startup>
</configuration>

今回の検証では、既存の ASP.NET Web アプリケーションの Forms 認証用の ASPNETDB.mdf を利用ました。

なので、上記 app.config で既存の ASPNETDB.mdf に接続できるように接続文字列を設定し、machineKey 要素、membership 要素、roleManager 要素の設定は既存の Web アプリの web.config と同じにしています。

machineKey 要素の設定まで同じにしたのは、MSDN ライブラリの How To: ASP.NET 2.0 で MachineKey を構成する方法 の「メンバシップ」のセクションに "暗号化パスワード フォーマットを選択すると、データの暗号化と暗号化解除のときに <machineKey> 設定が使用されます" という記述があったからです。

ただし、これは passwordFormat が "Encrypted" に設定されている場合のようで、デフォルトの "Hashed" の場合は関係なさそうです。

それから、ランタイムバージョンが .NET 2.0 になっているのは、.NET 4 では何故か MembershipUser が使えないからです。

オブジェクトブラウザを見ても MembershipUser 以外にも .NET 4 に含まれないクラスが多々あります。理由不明ですが、今日はもうこれ以上追求する気力がないです。(笑)

----- 2014/2/13 追記 -----

.NET 3.5 以前では System.Web.dll のみを参照設定に追加すれば使えた MembershipUser その他のクラスが .NET 4 では使えない理由が分かりました。

Microsoft の ASP.NET のサイトの ASP.NET 4 Breaking Changes という記事の MembershipUser and Other Types in the System.Web.Security Namespace Have Been Moved という記事に以下のように書いてありました。

"Some types that are used in ASP.NET membership have been moved from System.Web.dll to the new System.Web.ApplicationServices.dll assembly. The types were moved in order to resolve architectural layering dependencies between types in the client and in extended .NET Framework SKUs."

従って、.NET 4 以降では System.Web.ApplicationServices.dll も参照設定に追加しないと MembershipUser クラスは使えません。

ただし、"System.Web.ApplicationServices.dll was added to the list of referenced assemblies that is used by default by the ASP.NET compilation system." とのことなので、ASP.NET Web アプリケーションではプログラマが参照設定を追加する必要はないそうです。

詳しくは上に紹介した Microsoft のサイトの記事を見てください。

Tags: ,

Authentication

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  December 2019  >>
MoTuWeThFrSaSu
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar