使用ASP.NET SimpleMembership 提供者

by vivid 19. 六月 2013 14:37

.NET Magazine國際中文電子雜誌
者:許薰尹
稿:張智凱
文章編號:N130613702
出刊日期:2013/6/19

ASP.NET 會員服務(Membership)與角色服務(Role)在2.0版時(2005年發表),讓你能夠快速地建立會員服務的網站,並能透過角色做群組權限的管理。不過預設它只支援SQL Server資料庫與AD服務,若要使用其它資料庫來儲存會員帳戶資料,則需要自訂提供者(Provider);此外若要為使用者儲存特殊資訊,通常要搭配Profile服務。ASP.NET 4.5新增了新的角色(Roles)與會員服務(Memberships)提供者,協助會員網站的建置。本文將介紹預設ASP.NET MVC 4專案的會員服務機制,並將它移植到ASP.NET Web Forms類型的網站應用程式。

角色提供者(Role Providers)

ASP.NET 4.5中的角色提供者(Role Providers)包含了:

  • ActiveDirectoryRoleProvider:整合AD的群組。
  • SqlRoleProvider:可整合SQL Server資料庫。
  • WindowsTokenRoleProvider:使用Windows群組。

因為ActiveDirectoryRoleProvider與SqlRoleProvider的結構定死了,無法自行隨意更改結構,例如若使用SqlRoleProvider,你無法在資料庫資料表自行定義喜歡的資料表欄位儲存資料。因而,微軟另外提供了SimpleRoleProvider與UniversalProviders提供者來取代ActiveDirectoryRoleProvider與SqlRoleProvider提供者。

  • SimpleRoleProvider可整合SQL Server、SQL Server Compact Edition、SQL Azure等等資料庫。
  • UniversalProviders整合Entity Framework支援的資料庫。預設若是建立一個ASP.NET MVC 4 基本範本網站應用程式,網站組態檔案便設定使用UniversalProviders。UniversalProviders包含:
    • System.Web.Providers.DefaultMembershipProvider
    • System.Web.Providers.DefaultProfileProvider
    • System.Web.Providers.DefaultRoleProvider
    • System.Web.Providers.DefaultSessionStateProvider

這兩個提供者可以混合使用。

 

會員服務提供者(Membership Providers)

ASP.NET 4.5也提供了 SimpleMembershipProvider來取代舊版的ASP.NET Membership Provider。若要明確地設定網站應用程式要使用SimpleMembershipProvider與SimpleRoleProvider,可以在組態檔案中<system.web>區段內定義以下區段:

 

<roleManager enabled = "true"  defaultProvider = "SimpleRoleProvider">
  <providers>
    <clear/>
    <add name = "SimpleRoleProvider"  type = "WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
  </providers>
</roleManager>
<membership defaultProvider = "SimpleMembershipProvider">
  <providers>
    <clear/>
    <add name = "SimpleMembershipProvider" type = "WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
  </providers>
</membership>

 

建立ASP.NET MVC4應用程式

預設若選擇「網際網路應用程式」範本來建立ASP.NET MVC4應用程式, 專案中將包含一個AccountController.cs檔案,其中包含程式碼以透過SimpleMembershipProvider來建立會員資料網站。

從Visual Studio 2012開發工具 -「檔案」-「新增」-「專案」,在「新增專案」對話盒中選取程式語言,例如本範例選擇「Visual C#」,從「Web」分類中,選取「ASP.NET MVC 4 Web應用程式」,名稱部分使用預設的名稱;按下「確定」鍵。在新出現的「新ASP.NET MVC 4專案」對話盒中選取「網際網路應用程式」,請參考下圖所示:

clip_image002

圖 1:網際網路應用程式。

預設專案中已經自動參考SimpleMembershipProvider所需的WebMatrix.Data與WebMatrix.WebData等相關的組件,請參考下圖所示:

clip_image003

圖 2:網際網路應用程式範本專案自動參考SimpleMembershipProvider所需的WebMatrix.Data與WebMatrix.WebData等相關的組件。

若您建立的是空白專案,則可以使用NuGet從線上下載與安裝Microsoft.AspNet.WebPages.WebData與Microsoft.AspNet.WebPages.Data套件,這部分先略過,在《建立ASP.NET Web Forms應用程式》一節再來探討。

在Web.config檔案設定資料庫連線

專案建立之後,web.config檔案內包含一個名為「DefaultConnection」的連接字串設定,預設連結到localdb,就本範例而言,指明未來會員資料要儲存的資料庫檔案為「aspnet-MvcMembership-20130603121017」:

<connectionStrings>
    <add name = "DefaultConnection" connectionString = "Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcMembership-20130603121017;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MvcMembership-20130603121017.mdf" providerName = "System.Data.SqlClient" />
  </connectionStrings>


 

 

使用UsersContext類別建立資料庫

預設ASP.NET MVC 4網際網路應用程式範本專案引用了Entity Framework 5.0函式庫,採用Code First技術來建立會員資料庫。在Visual Studio 2012開發工具-「方案總管」-你的專案-「Models」目錄中,包含一個AccountModel.cs檔案,其中定義一個UsersContext類別,繼承了Entity Framework的DbContext類別,其建構函式中叫用DbContext建構函式,指定了連接字串的名稱為上述的「DefaultConnection」:

 

public class UsersContext : DbContext {
  public UsersContext( )
    : base( "DefaultConnection" ) {
  }

  public DbSet<UserProfile> UserProfiles { get; set; }
}

 

此外在「Models」目錄中AccountModel.cs檔案內也包含了一個UserProfile類別,程式如下:

[Table( "UserProfile" )]
public class UserProfile {
  [Key]
  [DatabaseGeneratedAttribute( DatabaseGeneratedOption.Identity )]
  public int UserId { get; set; }
  public string UserName { get; set; }
}

此類別用來定義未來透過Entity Framework Code First技術,要產生的資料庫資料表與欄位的結構描述資訊。資料表的名稱將會是「UserProfile」,資料表中將會儲存使用者的帳號與名稱,欄位名稱將會是「UserId」、「UserName」,您可以修改預設Visual Studio 2012工具產生的UserProfile類別,以屬性的方式定義額外想要存放的使用者相關資料。例如本文範例,在UserProfile類別內額外定義一個Country屬性,描述使用者所在國家。

 

 
[Table( "UserProfile" )]
public class UserProfile {
  [Key]
  [DatabaseGeneratedAttribute( DatabaseGeneratedOption.Identity )]
  public int UserId { get; set; }
  public string UserName { get; set; }
  public string Country { get; set; }
}

 

InitializeSimpleMembership attribute

檢視Visual Studio 2012開發工具-「方案總管」-你的專案-「Filters」目錄,其中有一個InitializeSimpleMembershipAttribute.cs檔案包含InitializeSimpleMembershipAttribute類別的定義,用來初始化會員資料庫:

 

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Web.Mvc;
using WebMatrix.WebData;
using MvcMembership.Models;

namespace MvcMembership.Filters {
  [AttributeUsage( AttributeTargets.Class | AttributeTargets.Method , AllowMultiple = false , Inherited = true )]
  public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute {
    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object( );
    private static bool _isInitialized;

    public override void OnActionExecuting( ActionExecutingContext filterContext ) {
      // 請確定一個應用程式啟動只起始一次 ASP.NET Simple Membership
      LazyInitializer.EnsureInitialized( ref _initializer , ref _isInitialized , ref _initializerLock );
    }

    private class SimpleMembershipInitializer {
      public SimpleMembershipInitializer( ) {
        Database.SetInitializer<UsersContext>( null );

        try {
          using ( var context = new UsersContext( ) ) {
            if ( !context.Database.Exists( ) ) {
              // 建立沒有 Entity Framework 移轉結構描述的 SimpleMembership 資料庫
              ( ( IObjectContextAdapter ) context ).ObjectContext.CreateDatabase( );
            }
          }

          WebSecurity.InitializeDatabaseConnection( "DefaultConnection" , "UserProfile" , "UserId" , "UserName" , autoCreateTables: true );
        } catch ( Exception ex ) {
          throw new InvalidOperationException( "無法起始 ASP.NET Simple Membership 資料庫。如需詳細資訊,請參閱 http://go.microsoft.com/fwlink/?LinkId=256588" , ex );
        }
      }
    }
  }
}


此類別中的程式碼檢查資料庫是否已存在,若不存在則叫用CreateDatabase方法來建立資料庫。最後再叫用了WebSecurity.InitializeDatabaseConnection方法來連接到會員資料庫。WebSecurity.InitializeDatabaseConnection方法設定autoCreateTables參數為true,表示資料庫中若不存在UserProfile資料表,則自動建立。同時,Controllers 目錄中預設的AccountController類別上方套用了InitializeSimpleMembership Attribute:

[InitializeSimpleMembership]
public class AccountController : Controller {

 

我們可以使用Memebership API來進行一些會員帳戶的初始化動作,例如在InitializeSimpleMembershipAttribute.cs檔案中WebSecurity.InitializeDatabaseConnection這行程式碼下方:

WebSecurity.InitializeDatabaseConnection( "DefaultConnection" , "UserProfile" , "UserId" , "UserName" , autoCreateTables: true );

加入以下程式碼,利用WebSecurity.UserExists方法判斷目前資料表中是否存在mary使用者,若不存在的話則叫用WebSecurity.CreateUserAndAccount方法建立使用者資料:

if ( !WebSecurity.UserExists( "mary" ) ) {
WebSecurity.CreateUserAndAccount( "mary" , "Pa$$w0rd" ,
new { UserName = "mary" , Country = "TW" } );
}

 

測試

基本上只要建立一個「網際網路應用程式」範本的ASP.NET MVC專案,會員服務功能便已啟用。我們可以在Visual Studio 2012中直接按F5來執行程式,點選右上方的「登入」連結,請參考下圖所示:

clip_image004

圖 3:點選「登入」連結。

使用程式建立的Mary帳號登入網站應用程式,請參考下圖所示:

clip_image005

圖 4:使用程式建立的Mary帳號登入網站應用程式。

登入成功後,右上角將顯示「Hello mary」訊息,請參考下圖所示:

clip_image006

圖 5:登入成功將顯示歡迎訊息。

檢視資料庫

從Visual Studio 2012開發工具 -「你的專案」-「App_Data」目錄中選取新建立的mdf資料庫檔案,按下滑鼠右鍵,從快捷選單選取「開啟」選項,請參考下圖所示:(若看不到檔案,請選取「方案總管」視窗上方的「顯示所有檔案」按鈕,再點選「重新整理」按鈕)

clip_image007

圖 6:開啟資料庫。

Visual Studio 2012會在「伺服器總管」視窗中顯示新開啟的資料庫,請參考下圖所示,在「資料連結」-「你的資料庫連接」-「資料表」,點選「UserProfile」,按下滑鼠右鍵,從快捷選單選取「顯示資料表資料」選項,就可以看到資料表中新建立一筆會員資料:

clip_image009

圖 7:顯示資料表資料。

讀取會員資料

未來若想要透過Membership API來讀取會員資料也相當的方便,例如修改範本專案HomeController類別下的Index方法,利用Entity Framework查詢使用者的country資料,放到ViewBag中傳遞到View:

public class HomeController : Controller {
  public ActionResult Index( ) {
    ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";

    var context = new UsersContext( );
    var username = User.Identity.Name;
    var user = context.UserProfiles.SingleOrDefault( u => u.UserName == username );
    if ( user != null ) {
      ViewBag.country = user.Country;
    }
    return View( );
  }

 

 

在Views\Home\Index.cshtml檔案中,加入以下程式片段,將登入使用者的所在國家名稱顯示在畫面上:

<h3>User Country :</h3>
@if ( @ViewBag.country != null ) {
@ViewBag.country
}

在Visual Studio 2012中直接按F5來執行程式,點選右上方的「登入」連結,當登入成功後,便可讀取使用者的所在國家,請參考下圖所示,

clip_image010

圖 8:讀取使用者的所在國家。

建立ASP.NET Web Forms應用程式

ASP.NET 4.5 Web Forms範本網站預設並不是使用SimpleMembershipProvider而是使用Universal Provider。不過ASP.NET 4.5 Web Forms和ASP.NET MVC 4底層都是ASP.NET,這些功能都可以互通,你只需要把ASP.NET MVC 4專案中設定手動移植到ASP.NET 4.5 Web Forms專案就行了。

我們來新增一個ASP.NET 4.5 Web Forms專案試看看,從Visual Studio 2012開發工具 -「檔案」-「新增」-「專案」,在「新增專案」對話盒中選取程式語言,例如本範例選擇「Visual C#」,從「Web」分類中,選取「ASP.NET Web Form應用程式」,名稱部分使用預設的名稱;按下「確定」鍵,請參考下圖所示:

clip_image012

圖 9:建立「ASP.NET Web Form應用程式」。

預設Visual Studio 2012工具會自動在Web.config檔案建立名稱為DefaultConnection的連接字串組態:

<connectionStrings>
<add name = "DefaultConnection" providerName = "System.Data.SqlClient" connectionString = "Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-WebSimpleMembership-20130531140622;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-WebSimpleMembership-20130531140622.mdf" />
</connectionStrings>

根據組態檔案的設定,預設會使用Universal Provider,首先將以下Web.config組態檔案中membership與roleManager的組態設定移除:

 

<membership defaultProvider = "DefaultMembershipProvider">
  <providers>
    <add name = "DefaultMembershipProvider" type = "System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName = "DefaultConnection" enablePasswordRetrieval = "false" enablePasswordReset = "true" requiresQuestionAndAnswer = "false" requiresUniqueEmail = "false" maxInvalidPasswordAttempts = "5" minRequiredPasswordLength = "6" minRequiredNonalphanumericCharacters = "0" passwordAttemptWindow = "10" applicationName = "/" />
  </providers>
</membership>
<roleManager defaultProvider = "DefaultRoleProvider">
  <providers>
    <add name = "DefaultRoleProvider" type = "System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName = "DefaultConnection" applicationName = "/" />
  </providers>
</roleManager>

 

安裝WebPages.Data與WebPages.WebData套件

下一步利用NuGet工具來安裝Microsoft.AspNet.WebPages.Data與Microsoft.AspNet.WebPages.WebData套件,步驟為:在Visual Studio 2012工具-「方案總管」-點選專案,按滑鼠右鍵,從快捷選單選取「管理NuGet套件」:

接著便會跳出「管理NuGet套件」對話盒,從線上搜尋「Microsoft.AspNet.WebPages 2 Web Data」進行安裝,請參考下圖所示:

clip_image014

圖 10:安裝Microsoft.AspNet.WebPages.Data與Microsoft.AspNet.WebPages.WebData套件。

NuGet會將此函式庫相依的WebPages.Data套件一併安裝,請參考下圖所示:

clip_image015

圖 11:安裝相依的WebPages.Data套件。

接下來在網站應用程式中加入一個類別,類別名稱可以隨意定,本文範例設定為「Account.cs」請參考下圖所示:

clip_image017

圖 12:加入一個Account.cs檔案。

在Account.cs檔案中,加入以下在ASP.NET MVC 4專案中AccountModels.cs中的UsersContext、UserProfile與SimpleMembershipInitializer類別程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Web;
using WebMatrix.WebData;

namespace WebSimpleMembership.App_Code {
  public class UsersContext : DbContext {
    public UsersContext( )
      : base( "DefaultConnection" ) {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
  }

  [Table( "UserProfile" )]
  public class UserProfile {
    [Key]
    [DatabaseGeneratedAttribute( DatabaseGeneratedOption.Identity )]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string Country { get; set; }
  }

  public class SimpleMembershipInitializer {
    public SimpleMembershipInitializer( ) {
      Database.SetInitializer<UsersContext>( null );

      try {
        using ( var context = new UsersContext( ) ) {
          if ( !context.Database.Exists( ) ) {
            // 建立沒有 Entity Framework 移轉結構描述的 SimpleMembership 資料庫
            ( ( IObjectContextAdapter ) context ).ObjectContext.CreateDatabase( );
          }
        }

        WebSecurity.InitializeDatabaseConnection( "DefaultConnection" , "UserProfile" , "UserId" , "UserName" , autoCreateTables: true );

        if ( !WebSecurity.UserExists( "mary" ) ) {
          WebSecurity.CreateUserAndAccount( "mary" , "Pa$$w0rd" ,
             new { UserName = "mary" , Country = "TW" } );
        }

      } catch ( Exception ex ) {
        throw new InvalidOperationException( "無法起始 ASP.NET Simple Membership 資料庫。如需詳細資訊,請參閱 http://go.microsoft.com/fwlink/?LinkId=256588" , ex );
      }
    }
  }

}


 

最後在Global.asax.cs檔案內,網站啟動時的Application_Start事件中,進行資料庫、資料表的初始化動作,利用new關鍵字,建立SimpleMembershipInitializer物件實體:

void Application_Start( object sender , EventArgs e ) {
  // 應用程式啟動時執行的程式碼
  new SimpleMembershipInitializer( );
  BundleConfig.RegisterBundles( BundleTable.Bundles );
  AuthConfig.RegisterOpenAuth( );
  RouteConfig.RegisterRoutes( RouteTable.Routes );
}

 

測試

在Visual Studio 2012中直接按F5來執行程式,請參考下圖所示:

clip_image019

圖 13:測試ASP.NET Web Forms網站應用程式。

你可以直接使用Mary帳號登入,請參考下圖所示:clip_image021

圖 14:登入測試。

登入成功後,右上角將顯示「Hello mary」訊息,請參考下圖所示:clip_image023

圖 15:登入成功將顯示歡迎訊息。

檢視網站的App_Data目錄,將建立一個mdf資料庫,請參考下圖所示:(若看不到檔案,請選取「方案總管」視窗上方的「顯示所有檔案」按鈕,再點選「重新整理」按鈕)

clip_image024

圖 16:App_Data目錄,將建立一個mdf資料庫。

從Visual Studio 2012開發工具 -「你的專案」-「App_Data」目錄中選取新建立的mdf資料庫檔案,按下滑鼠右鍵,從快捷選單選取「開啟」選項,請參考下圖所示:

clip_image025

圖 17:開啟資料庫。

Visual Studio 2012會在「伺服器總管」視窗中顯示新開啟的資料庫,請參考下圖所示,在「資料連結」-「你的資料庫連接」-「資料表」,點選「UserProfile」,按下滑鼠右鍵,從快捷選單選取「顯示資料表資料」選項,就可以看到資料表中新建立一筆會員資料:clip_image027

圖 18:顯示資料表資料。

Tags:

.NET Magazine國際中文電子雜誌 | ASP.NET | ASP.NET MVC | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List