คุณสมบัติการเป็นสมาชิก ASP.NET ช่วยลดจำนวนรหัสที่คุณต้องเขียนเพื่อตรวจสอบสิทธิ์ผู้ใช้และจัดเก็บข้อมูลประจำตัวของพวกเขา เพื่ออ้าง MSDN:
"สมาชิก ASP.NET ให้วิธีการในตัวในการตรวจสอบและจัดเก็บข้อมูลรับรองผู้ใช้คุณใช้การเป็นสมาชิก ASP.NET พร้อมการตรวจสอบความถูกต้องแบบฟอร์มและ / หรือด้วยการควบคุมการเข้าสู่ระบบ ASP.NET สำหรับการตรวจสอบผู้ใช้"
ผู้ให้บริการสมาชิกจะต้องระบุไว้ในไฟล์การกำหนดค่า web.config คุณสามารถใช้ผู้ให้บริการที่กำหนดเองของคุณเองหรือหนึ่งในผู้ให้บริการเริ่มต้นที่จัดส่งด้วย. NET Framework เช่นผู้ให้บริการ SQLMEMBERSHIPPROVIDER
ข้อมูลที่เกี่ยวข้องกับผู้ใช้ทั้งหมดจะถูกเก็บไว้ในชุดของตารางที่ใช้โดยระบบสมาชิก ASP.NET ในกรณีส่วนใหญ่คุณจะใช้ตารางหนึ่งชุดต่อเว็บแอปพลิเคชัน อย่างไรก็ตามคุณสามารถนำชุดเดียวกันกลับมาใช้ใหม่เพื่อจัดเก็บข้อมูลรับรองผู้ใช้ของเว็บแอปพลิเคชันหลายรายการ สิ่งนี้ช่วยให้คุณสามารถสร้างเว็บแอปพลิเคชั่นเดียวที่ทำหน้าที่เป็นพอร์ทัลที่ช่วยให้คุณสามารถเข้าสู่แอปพลิเคชัน "เสมือน" เหล่านี้ได้อย่างใดอย่างหนึ่ง
อย่างไรก็ตามสิ่งนี้เป็นไปไม่ได้นอกกรอบ คุณมีงานล่วงหน้าก่อนที่คุณจะสามารถสนับสนุนแอปพลิเคชันแบบไดนามิกดังกล่าว
มาเริ่มกันเถอะ ...
เริ่มต้นด้วยการตรวจสอบรายการ web.config ต่อไปนี้:
รายชื่อ 1 - การกำหนดค่าสมาชิก ASP.NET ASP.NET
< membership defaultProvider = " SqlProvider " >
< providers >
< clear />
< add name = " SqlProvider "
type = " System.Web.Security.SqlMembershipProvider "
connectionStringName = " YourConnectionStringName "
applicationName = " MyApplication "
... />
</ providers >
</ membership >การตั้งค่าเหล่านี้ตั้งค่าเว็บแอปพลิเคชันของคุณเพื่อใช้ SQLMEMBERSHIPPROVIDER เพื่อจัดการข้อมูลรับรองผู้ใช้ของคุณ ข้อมูลทั้งหมดที่เกี่ยวข้องกับผู้ใช้ของคุณจะถูกเก็บไว้ในตารางสมาชิก ASP.NET เริ่มต้น
หมายเหตุ : บทความนี้ไม่ใช่ไพรเมอร์ในการเป็นสมาชิก ASP.NET คุณควรคุ้นเคยกับมัน ใช้เครื่องมือลงทะเบียนเซิร์ฟเวอร์ ASP.NET SQL (ASPNET_REGSQL.EXE) สำหรับการตั้งค่าฐานข้อมูลของคุณ
ดังที่ได้กล่าวไว้ก่อนที่คุณจะสามารถจัดเก็บข้อมูลรับรองผู้ใช้ของเว็บแอปพลิเคชันหลายตัวในชุดตารางเดียวกัน แต่ละเว็บแอปพลิเคชันจะแยกข้อมูลผู้ใช้ของพวกเขาโดยแบ่งพาร์ติชันในสิ่งที่ฉันเรียกว่าบริบทแอปพลิเคชัน บริบทแอปพลิเคชันนี้ถูกกำหนดโดยคุณสมบัติแอปพลิเคชันของผู้ให้บริการสมาชิก อย่างที่คุณเห็นในรายการ 1 ชื่อแอปพลิเคชันคือ "myApplication"
SQLMEMBERSHIPPROVIDER ใช้การตั้งค่านี้เพื่อพิจารณาว่าบริบทใดที่ควรใช้งานข้อมูลผู้ใช้ทั้งหมดที่เชื่อมโยงกับชื่อแอปพลิเคชันนี้จะสามารถเข้าถึงได้โดย ASP.NET MEMBERHISHIP LIBRARY และการควบคุมการเข้าสู่ระบบ
น่าเสียดายที่การตั้งค่านี้มีการกำหนดแบบคงที่ใน web.config คุณไม่สามารถเปลี่ยนแปลงได้อย่างง่ายดายในระหว่างการรันไทม์ หากคุณต้องการสนับสนุนแอปพลิเคชันแบบไดนามิกคุณต้องมีวิธีควบคุมมูลค่าของคุณสมบัติแอปพลิเคชันของผู้ให้บริการ การแก้ปัญหาอยู่ในการสร้างผู้ให้บริการสมาชิก ASP.NET ของคุณเอง
SQLMEMBERSHIPPROVIDER ดึงค่าสำหรับคุณสมบัติ ApplicationName จากการตั้งค่าการกำหนดค่าที่มีอยู่ในไฟล์ web.config เราต้องการเปลี่ยนค่าที่ Getter ของคุณสมบัตินี้ส่งคืน
เมื่อเข้าสู่ระบบในผู้ใช้ควรทำให้ความตั้งใจของเขาชัดเจนในคำอื่น ๆ เขาต้องระบุแอปพลิเคชันเสมือนใดที่เขาต้องการเข้าถึง เพื่อจุดประสงค์นี้ฉันต้องการให้ผู้ใช้ไม่เพียง แต่ระบุชื่อผู้ใช้และรหัสผ่านของเขาเท่านั้น แต่ยังรวมถึงแอปพลิเคชันเสมือนจริงที่เขาต้องการเข้าถึง จากมุมมองของผู้ใช้ฉันเรียกแอปพลิเคชันเสมือนนี้โดเมน
ตัวอย่างเช่นสมมติว่าคุณได้สร้างฐานข้อมูล SQL Server ที่เรียกว่า AspnetMembership ซึ่งมีตารางสมาชิก ASP.NET ฐานข้อมูลนี้มีแอปพลิเคชันเสมือนต่อไปนี้ที่กำหนดไว้ในตาราง ASPNET_APPLICATIONS:
แอปพลิเคชั่นเสมือนจริงแต่ละตัวมีผู้ใช้ที่มีชื่อผู้ใช้ "cgeers" ตอนนี้ถ้าฉันต้องการเข้าสู่แอปพลิเคชัน Northwind ฉันต้องป้อนชื่อผู้ใช้ของฉันเป็น "Northwind cgeers" สำหรับแอปพลิเคชัน Adventureworks นี่จะเป็น "Adventureworks cgeers"
ส่วนก่อนหน้าชื่อผู้ใช้คือชื่อแอปพลิเคชันหรือเท่าที่ผู้ใช้กังวลว่านี่คือโดเมนที่เขาต้องป้อนเพื่อระบุแอปพลิเคชันเสมือนที่เขาต้องการเข้าถึง โดเมนและชื่อผู้ใช้จะถูกคั่นด้วยแบ็คสแลช
เมื่อผู้ใช้เข้าสู่ระบบในการใช้การควบคุมการเข้าสู่ระบบ ASP.NET เราต้องแยกโดเมนที่เขาป้อนและจัดเก็บสิ่งนี้ในสถานที่ที่ผู้ให้บริการสมาชิกที่กำหนดเองของเราสามารถเข้าถึงได้ อย่างไรก็ตามเราต้องคำนึงถึงว่า ASP.NET ทำงานในสภาพแวดล้อมแบบมัลติเธรด แต่ละคำขอที่ได้รับจาก ASP.NET จะได้รับการจัดการโดยเธรดแยกต่างหาก เราไม่สามารถจัดเก็บโดเมนในสถานที่ใดก็ได้การร้องขอที่เข้ามาอื่น ๆ อาจเขียนทับ จะต้องเชื่อมโยงกับคำขอเดียว
สถานที่ที่เหมาะสำหรับการจัดเก็บข้อมูลบริบทที่เชื่อมโยงกับคำขอส่วนบุคคลคือบริบท HTTP ปัจจุบัน ข้อมูลบริบทนี้ถูกห่อหุ้มโดยคลาส HTTPContext
เริ่มต้น Visual Studio และสร้างโซลูชันว่างเปล่าใหม่ที่เรียกว่า "AspnetDynamicapplications" ถัดไปเพิ่มโครงการห้องสมุดคลาสใหม่ลงในโซลูชันที่ชื่อว่า "cgeers.web.security" เพิ่มการอ้างอิงไปยัง System.Configuration และ System.web Assemblies ผู้ให้บริการที่กำหนดเองของเราจะลงมาจาก Sqlmembershipprovider เริ่มต้นดังนั้นจึงจำเป็นต้องมีการอ้างอิงเหล่านี้
รูปที่ 1 - โซลูชัน Visual Studio

เปลี่ยนชื่อไฟล์ class1.cs ที่สร้างขึ้นโดยอัตโนมัติเป็น dynamicapplicationssqlmembershipprovider.cs และเพิ่มรหัสที่แสดงในรายการ 2
รายการ 2 - Dynamicapplicationssqlmembershipprovider
public class DynamicApplicationsSqlMembershipProvider : SqlMembershipProvider
{
#region Fields
private const string ApplicationNameSetting = "ApplicationName" ;
#endregion
public override string ApplicationName
{
get
{
HttpContext context = HttpContext . Current ;
if ( context == null )
{
throw new InvalidOperationException ( "Http context cannot be null." ) ;
}
string applicationName = String . Empty ;
if ( context . Items . Contains ( ApplicationNameSetting ) )
{
if ( ! String . IsNullOrEmpty ( ( string ) context . Items [ ApplicationNameSetting ] ) )
{
applicationName = ( string ) context . Items [ ApplicationNameSetting ] ;
}
}
return applicationName ;
}
set
{
base . ApplicationName = value ;
}
}
}ในขณะที่คุณสามารถเห็นผู้ให้บริการสมาชิกที่กำหนดเองของเราลงมาจาก SQLMEMMEMBERSHIPPROVIDER เริ่มต้นและแทนที่คุณสมบัติ ApplicationName เราไม่ได้เกี่ยวข้องกับ setter เฉพาะกับ getter เมื่อผู้ให้บริการอ่านคุณสมบัติ ApplicationName เราจะได้รับการจัดการกับบริบท HTTP ปัจจุบันโดยเรียกคุณสมบัติปัจจุบันคงที่ของคลาส HTTPContext วัตถุ HTTPContext ที่ได้รับคุณสมบัติการรวบรวมคีย์/ค่าที่เรียกว่ารายการ คอลเลกชันนี้จัดเก็บชื่อแอปพลิเคชันในรายการที่ระบุโดยคีย์ "ApplicationName" ชื่อของคีย์นี้เป็นสิ่งที่คุณต้องกำหนดเวลาออกแบบ
ตอนนี้ทุกครั้งที่ผู้ให้บริการสมาชิกที่กำหนดเองของเราจำเป็นต้องกำหนดชื่อแอปพลิเคชันที่เรียกว่าคุณสมบัติ ApplicationName ซึ่งจะดึงค่าจากบริบท HTTP ปัจจุบัน สิ่งนี้ใช้งานได้ในสภาพแวดล้อมแบบมัลติเธรดของ ASP.NET เนื่องจากแต่ละคำขอเชื่อมโยงกับบริบท HTTP ของตัวเอง
ตอนนี้เราเป็นผู้ให้บริการสมาชิกที่กำหนดเองที่ดึงค่าสำหรับคุณสมบัติแอปพลิเคชันชื่อจากบริบท HTTP Currect เรายังต้องหาวิธีที่จะจัดเก็บชื่อแอปพลิเคชันในบริบท HTTP
ครั้งแรกที่ผู้ใช้ระบุแอปพลิเคชันเสมือนจริงหรือโดเมนที่เขาต้องการเข้าถึงคือเมื่อเขาเข้าสู่ระบบตามที่กล่าวไว้ก่อนหน้านี้ผู้ใช้จะต้องป้อนชื่อผู้ใช้ของเขาในรูปแบบ <domain><username> เราต้องสร้างการควบคุมการเข้าสู่ระบบของเราเองซึ่งลงมาจากการควบคุมการเข้าสู่ระบบ ASP.NET เมื่อการตรวจสอบผู้ใช้เราจำเป็นต้องแยกโดเมนที่ป้อนและบันทึกไว้ในบริบท HTTP ปัจจุบัน
เพิ่มโครงการใหม่โดยใช้เทมเพลตไลบรารีคลาสไปยังโซลูชันของคุณที่เรียกว่า "cgeers.web.ui.webcontrols" เพิ่มการอ้างอิงต่อไปนี้ในโครงการ:
ถัดไปลบไฟล์ class1.cs ที่สร้างขึ้นโดยอัตโนมัติและเพิ่มคลาสใหม่ที่เรียกว่า DynamicapplicationsLogin เนื่องจากรหัสสำหรับคลาสนี้ค่อนข้างยาวฉันเลือกที่จะแบ่งมันออกเป็นหลายรายการ หลังจากแต่ละรายการคำอธิบายสั้น ๆ ของรหัสจะถูกเพิ่ม
รายการ 3 - DynamicapplicationSlogin ควบคุมคุณสมบัติส่วนตัว
public class DynamicApplicationsLogin : Login
{
#region Fields
private string _fullUserName ;
#endregion
#region Properties
private string ApplicationName
{
get
{
string [ ] data = base . UserName . Split ( @"" . ToCharArray ( ) , 2 ) ;
string applicationName = ( data . Length == 2 ) ? data [ 0 ] : String . Empty ;
return applicationName ;
}
}
private string BaseUserName
{
get
{
string [ ] data = base . UserName . Split ( @"" . ToCharArray ( ) , 2 ) ;
string userName = ( data . Length == 2 ) ? data [ 1 ] : base . UserName ;
return userName ;
}
}
#endregion
// ...
}ในขณะที่คุณสามารถเห็นการควบคุม Dynamicapplicationslogin ลงมาจากการควบคุมการเข้าสู่ระบบ ASP.NET มาตรฐานและฟิลด์ที่เรียกว่า _FulluserName และแอปพลิเคชันคุณสมบัติส่วนตัวสองรายการและเพิ่ม baseUserName
เนื่องจากผู้ใช้เข้าสู่โดเมนและชื่อผู้ใช้เป็นตัวควบคุมกล่องข้อความเดียวกันเราจึงจำเป็นต้องแยกส่วนเหล่านี้ ในขณะที่คุณอาจคาดเดาคุณสมบัติแอปพลิเคชันที่แยกโดเมนและชื่อ baseUserName ส่งคืนชื่อผู้ใช้ ตัวอย่างเช่นหากผู้ใช้เข้าสู่ Northwind CGEERS คุณสมบัติ ApplicationName จะส่งคืน "Northwind" และคุณสมบัติ baseUserName จะกลับ "cgeers"
รายการ 4 - Dynamicapplicationslogin ควบคุมวิธีการ onauthenticate
protected override void OnAuthenticate ( AuthenticateEventArgs e )
{
HttpContext context = HttpContext . Current ;
if ( context == null )
{
throw new InvalidOperationException ( "Http context cannot be null." ) ;
}
MembershipProvider provider = Membership . Provider ;
if ( provider == null )
{
throw new InvalidOperationException ( "MembershipProvider cannot be null." ) ;
}
provider = provider as DynamicApplicationsSqlMembershipProvider ;
if ( provider == null )
{
throw new InvalidOperationException (
"The specified MembershipProvider must be of type DynamicApplicationsSqlMembershipProvider." ) ;
}
// Store the application name in the current Http context's items collections
context . Items [ "ApplicationName" ] = ApplicationName ;
// Validate the user
_fullUserName = UserName ;
UserName = BaseUserName ;
base . OnAuthenticate ( e ) ;
}ถัดไปคุณจะต้องแทนที่วิธี onauthenticate ของการควบคุมการเข้าสู่ระบบเพื่อให้แน่ใจว่าผู้ใช้ได้รับการตรวจสอบความถูกต้องภายในบริบทแอปพลิเคชันที่ถูกต้อง (แอปพลิเคชันเสมือน)
ก่อนอื่นวิธีนี้จะดึงการอ้างอิงไปยังบริบท HTTP ปัจจุบันจากนั้นจะตรวจสอบว่าผู้ให้บริการสมาชิกที่โหลดนั้นเป็นแบบไดนามิกที่กำหนดเองของเรา จากนั้นโดเมนที่ป้อนหรือชื่อแอปพลิเคชันจะถูกเก็บไว้ในคอลเลกชันรายการบริบท HTTP ปัจจุบันเพื่อให้ผู้ให้บริการสมาชิกของเราสามารถดึงค่าที่ถูกต้องสำหรับคุณสมบัติแอปพลิเคชันชื่อ
สุดท้าย แต่ไม่ท้ายสุดค่าคุณสมบัติของชื่อผู้ใช้ถูกตั้งค่าให้มีเฉพาะชื่อผู้ใช้โดยกำหนดคุณสมบัติ baseUserName ให้กับมัน ฟิลด์ส่วนตัว _fullusername จัดเก็บค่าที่ผู้ใช้ป้อนชั่วคราว (ชื่อผู้ใช้โดเมน) คุณจะเห็นว่าฟิลด์นี้ใช้ในภายหลังอย่างไร
หลังจากชื่อแอปพลิเคชันถูกเก็บไว้ในบริบท HTTP และคุณสมบัติชื่อผู้ใช้เท่านั้นที่มีชื่อผู้ใช้เท่านั้นที่เรียกว่าการใช้งานพื้นฐานซึ่งจะทำให้ชื่อผู้ใช้ได้รับการตรวจสอบความถูกต้องภายในบริบทแอปพลิเคชันที่ถูกต้อง
รายการ 5 -dynamicapplicationslogin ควบคุมวิธีการ onloginerror
protected override void OnLoginError ( EventArgs e )
{
UserName = _fullUserName ;
base . OnLoginError ( e ) ;
}แทนที่วิธี OnLogInError และก่อนที่จะเรียกการใช้งานฐานกำหนดฟิลด์ _fullusername ให้กับคุณสมบัติชื่อผู้ใช้ เมื่อตรวจสอบสิทธิ์ผู้ใช้ (วิธีการ onauthenticate) คุณสมบัติชื่อผู้ใช้จะต้องมีชื่อผู้ใช้เท่านั้นและไม่ใช่โดเมน แต่เมื่อการตรวจสอบความถูกต้องคุณต้องตรวจสอบให้แน่ใจว่าข้อความที่ผู้ใช้ป้อนในตัวควบคุมกล่องข้อความที่แสดงชื่อผู้ใช้จะถูกรีเซ็ตเป็นค่าที่ผู้ใช้ป้อนเริ่มต้น อื่น ๆ อาจทำให้ผู้ใช้สับสนหากโดเมนที่เขาป้อนหายไป
รายการ 6 - วิธีการควบคุม dynamicapplicationslogin onloggedIn
protected override void OnLoggedIn ( EventArgs e )
{
UserName = _fullUserName ;
HttpContext context = HttpContext . Current ;
if ( context == null )
{
throw new InvalidOperationException ( "Http context cannot be null." ) ;
}
string userName = BaseUserName ;
MembershipUser user = Membership . GetUser ( userName ) ;
if ( user != null )
{
string userData = String . Format ( "AN={0};" , ApplicationName ) ;
HttpCookie cookie = FormsAuthenticationHelper . StoreUserDataInAuthenticationCookie (
userName , userData , RememberMeSet
) ;
// Manually add the cookie to the Cookies collection
context . Response . Cookies . Add ( cookie ) ;
}
}ในการควบคุม DynamicapplicationSlogin ให้เสร็จสิ้นคุณต้องแทนที่วิธี onloggedIn ชื่อแอปพลิเคชันจะถูกเก็บไว้ในคุณสมบัติ UserData ของ FormSauthenticationTicket ตั๋วตรวจสอบสิทธิ์นี้ใช้โดยการตรวจสอบความถูกต้องแบบฟอร์มเพื่อระบุผู้ใช้ที่ได้รับการรับรองความถูกต้อง ที่นี่เราเก็บไว้ในคุกกี้และเพิ่มลงในการตอบสนองของบริบท HTTP ปัจจุบัน ในภายหลังคุณจะเห็นว่าทำไมสิ่งนี้จึงจำเป็น
คุณจะดูรายการ 6 คุณจะเห็นว่าคุกกี้ที่มีตั๋วการตรวจสอบความถูกต้องแบบฟอร์มถูกสร้างขึ้นโดยคลาสผู้ช่วยที่เรียกว่า FormsauthenticationHelper นี่คือคลาสผู้ช่วยแบบคงที่ซึ่งมีเพียงวิธีเดียวเท่านั้นคือ StoreUserDatainauthenticationCookie
เพิ่มคลาสใหม่ที่เรียกว่า FormSauthenticationHelper ลงในโครงการ CGEERS.WEB.Security และเพิ่มรหัสที่แสดงในรายการ 7
รายการ 7 - FormSauthenticationHelper
public static class FormsAuthenticationHelper
{
public static HttpCookie StoreUserDataInAuthenticationCookie (
string userName , string userData , bool persistent )
{
if ( String . IsNullOrEmpty ( userName ) )
{
throw new InvalidOperationException ( "UserName cannot be null or empty." ) ;
}
if ( String . IsNullOrEmpty ( userData ) )
{
throw new InvalidOperationException ( "User data cannot be null or empty." ) ;
}
// Create the cookie that contains the forms authentication ticket
HttpCookie cookie = FormsAuthentication . GetAuthCookie ( userName , persistent ) ;
// Get the FormsAuthenticationTicket out of the encrypted cookie
FormsAuthenticationTicket ticket = FormsAuthentication . Decrypt ( cookie . Value ) ;
// Create a new FormsAuthenticationTicket that includes our custom user data
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket ( ticket . Version ,
ticket . Name ,
ticket . IssueDate ,
ticket . Expiration ,
persistent ,
userData ) ;
// Update the cookie's value to use the encrypted version of our new ticket
cookie . Value = FormsAuthentication . Encrypt ( newTicket ) ;
// Return the cookie
return cookie ;
}
}Method storeUserDatainauthenticationCookie (... ) ดึงคุกกี้สำหรับผู้ใช้ที่ระบุ (พารามิเตอร์ชื่อผู้ใช้) ที่มีตั๋วการตรวจสอบความถูกต้องแบบฟอร์ม ถัดไปคุกกี้จะถูกถอดรหัสเพื่อเข้าถึงวัตถุ FormSauthenticationTicket จากนั้นรูปแบบใหม่นี้สร้างขึ้นตามตั๋วเก่าและค่าที่มีอยู่ในพารามิเตอร์ UserData จะถูกเก็บไว้ในตั๋วนี้ เป็นขั้นตอนสุดท้ายวัตถุ FormSauthenticationTicket ใหม่จะถูกเก็บไว้ในคุกกี้ที่เข้ารหัส
หมายเหตุ : ร้านค้าควบคุม DynamicapplicationSlogin ส่งคุกกี้นี้กลับไปยังผู้ใช้ดังนั้นลูกค้าจึงต้องสนับสนุนคุกกี้!
มาสรุปสิ่งที่เรามี
ดังนั้นเราจึงมีผู้ให้บริการสมาชิกที่กำหนดเองที่สามารถขอบริบทแอปพลิเคชันที่จะดำเนินการและเรามีการควบคุมการเข้าสู่ระบบที่กำหนดเองที่ระบุบริบทนี้โดยกำหนดให้ผู้ใช้นำหน้าชื่อผู้ใช้ของพวกเขาด้วยโดเมน (= ชื่อแอปพลิเคชัน)
วิธีนี้ใช้งานได้ค่อนข้างดีหากเว็บแอปพลิเคชันของคุณประกอบด้วยหน้าเข้าสู่ระบบเท่านั้น โปรดจำไว้ว่าผู้ให้บริการสมาชิกที่กำหนดเองกำหนดบริบทแอปพลิเคชันโดยการอ่านชื่อแอปพลิเคชันที่เก็บไว้ในบริบท HTTP ปัจจุบัน ด้วยแต่ละคำขอที่คุณทำบริบท HTTP ใหม่จะถูกสร้างขึ้น เมื่อเข้าสู่ระบบในชื่อแอปพลิเคชันจะถูกเก็บไว้อย่างชัดเจนภายในบริบท HTTP อย่างไรก็ตามสำหรับคำขอที่ตามมาใด ๆ นี่ไม่ใช่กรณี อย่างใดเราต้องตรวจสอบให้แน่ใจว่าบริบท HTTP เริ่มต้นอย่างถูกต้องด้วยชื่อแอปพลิเคชันพร้อมคำขอแต่ละครั้งหลังจากผู้ใช้เข้าสู่ระบบ
ดังที่ได้กล่าวไว้ก่อนหน้านี้การควบคุม DynamicApplicationLogin จะส่งคุกกี้ที่เข้ารหัสไปยังผู้ใช้หลังจากลงชื่อเข้าใช้สำเร็จคุกกี้นี้มีชื่อแอปพลิเคชันและถูกส่งไปพร้อมกับคำขอที่ตามมาแต่ละครั้ง Voila ตอนนี้ทั้งหมดที่เราต้องการคือวิธีการแทรกตรรกะบางอย่างลงในท่อขอ ASP.NET เพื่ออ่านเนื้อหาของคุกกี้นี้และจัดเก็บชื่อแอปพลิเคชันที่ดึงมาในบริบท HTTP
โมดูล HTTP เหมาะสำหรับสถานการณ์นี้ โมดูล HTTP ถูกเรียกใช้ทุกคำขอและรันก่อนและหลังการร้องขอจะถูกประมวลผล
เพิ่มคลาสใหม่ที่เรียกว่า DynamicapplicationsModule ลงในโครงการ CGEERS.WEB.Security คลาสนี้จำเป็นต้องใช้อินเตอร์เฟส IHTTPModule รหัสสำหรับโมดูล HTTP นี้จะแสดงในรายการ 8
รายการ 8 - DynamicapplicationsModule
public class DynamicApplicationsModule : IHttpModule
{
#region Fields
private const string ApplicationNameSetting = "ApplicationName" ;
#endregion
#region IHttpModule Members
public void Dispose ( )
{ }
public void Init ( HttpApplication context )
{
context . AuthenticateRequest += DetermineApplicationName ;
}
#endregion
private static void DetermineApplicationName ( object sender , EventArgs e )
{
// Access the current Http application.
HttpApplication application = sender as HttpApplication ;
if ( application == null )
{
throw new InvalidOperationException ( "Http application cannot be null." ) ;
}
// Get the HttpContext for the current request.
HttpContext context = application . Context ;
if ( context == null )
{
throw new InvalidOperationException ( "Http context cannot be null." ) ;
}
// Read the application name stored in the FormsAuthenticationTicket
string applicationName = String . Empty ;
if ( context . Request . IsAuthenticated )
{
FormsIdentity identity = context . User . Identity as FormsIdentity ;
if ( identity != null )
{
FormsAuthenticationTicket ticket = identity . Ticket ;
if ( ticket != null )
{
applicationName = ticket . GetApplicationName ( ) ;
}
}
}
// Store the application name in the Items collection of the per-request http context.
// Storing it in the session state is not an option as the session is not available at this
// time. It is only available when the Http application triggers the AcquireRequestState event.
context . Items [ ApplicationNameSetting ] = applicationName ;
}
}เมธอด init (... ) เริ่มต้นโมดูล HTTP และเตรียมการเพื่อจัดการคำขอ ที่นี่เหตุการณ์ AuthenticAterequest ของ httpapplication ถูกเชื่อมต่อกับตัวจัดการเหตุการณ์ DECTEPPLICATIONNAME
ตัวจัดการเหตุการณ์ DECENINEAPPLICALNAME (... ) ตรวจสอบว่าการจัดการกับคำขอที่ได้รับการรับรองความถูกต้องและหากเรียกใช้ตั๋ว FormSauthentication ที่ส่งโดยลูกค้า
ตั๋วนี้ระบุบริบทของแอปพลิเคชันที่จะใช้งาน ชื่อแอปพลิเคชันถูกสกัดจากตั๋วโดยใช้วิธี getApplicationName () ของ FormSauthenticationTicket () นี่เป็นวิธีการขยายฉันจะกล่าวถึงในส่วนต่อไปนี้
ในที่สุดหลังจากแยกชื่อแอปพลิเคชันออกจากตั๋วมันจะถูกเก็บไว้ในบริบท HTTP เพื่อให้ผู้ให้บริการสมาชิกที่กำหนดเองของเราสามารถอ่านได้
เพิ่มคลาสใหม่ที่เรียกว่า FormSauthenticationTicketExtensions ลงในโครงการ CGEERS.WEB.Security และเพิ่มรหัสที่แสดงในรายการ 9
รายการ 9 - FormSauthenticationTicketextensions
internal static class FormsAuthenticationTicketExtensions
{
public static string GetApplicationName ( this FormsAuthenticationTicket ticket )
{
// Check if the application name (AN=) is stored in the ticket's userdata.
string applicationName = String . Empty ;
List < string > settings = new List < string > ( ticket . UserData . Split ( ';' ) ) ;
foreach ( string s in settings )
{
string setting = s . Trim ( ) ;
if ( setting . StartsWith ( "AN=" ) )
{
int startIndex = setting . IndexOf ( "AN=" ) + 3 ;
applicationName = setting . Substring ( startIndex ) ;
break ;
}
}
return applicationName ;
}
}อย่างที่คุณเห็นในรายการ 6 การควบคุม DynamicApplicationLogin บันทึกชื่อแอปพลิเคชันในคุณสมบัติ UserData ของ FormSauthenticationTicket โดยก่อนหน้าด้วยคำนำหน้า "An =" ดังนั้นวิธีการขยายนี้จำเป็นต้องคำนึงถึงสิ่งนี้เมื่อดึงชื่อแอปพลิเคชันจาก FormSauthenticationTicket
หมายเหตุ : อย่าลังเลที่จะปรับปรุงเกี่ยวกับวิธีการจัดเก็บชื่อแอปพลิเคชันภายในตั๋ว แต่อย่าลืมใช้ระบบเดียวกันสำหรับการควบคุม DynamicapplicationSlogin และวิธีการขยายนี้
คล้ายกับการควบคุม DynamicApplicationSlogin ฉันได้สร้างการควบคุมที่สืบเชื้อสายมาจากการควบคุม ASP.NET PasswordRecovery และ ChangePassword หากคุณต้องการให้ผู้ใช้สามารถดึงรหัสผ่านของเขาและ/หรือเปลี่ยนได้คุณต้องใช้การควบคุมเหล่านี้ พวกเขาตรวจสอบให้แน่ใจว่าทุกอย่างถูกดำเนินการภายในบริบทแอปพลิเคชันที่ถูกต้อง
การใช้งานมีความคล้ายคลึงกับการควบคุม DynamicapplicationSlogin มากดังนั้นฉันจะไม่แสดงรายการรหัสของการควบคุมเหล่านี้ที่นี่ หากคุณต้องการตรวจสอบซอร์สโค้ดของตัวควบคุมเหล่านี้ให้ดาวน์โหลดซอร์สโค้ดที่มาพร้อมกับบทความนี้ คุณสามารถค้นหาการควบคุมเหล่านี้ได้ในโครงการ cgeers.web.ui.webcontrols
ซอร์สโค้ดที่มาพร้อมกับบทความนี้ยังมีโครงการเว็บแอปพลิเคชันตัวอย่างที่แสดงให้เห็นถึง DynamicapplicationsSqlMembershipprovider การควบคุมการเข้าสู่ระบบใหม่โมดูล HTTP ที่กำหนดเองของเรา ... และอื่น ๆ
รูปที่ 2 - โซลูชัน Visual Studio

ในการเรียกใช้แอปพลิเคชันตัวอย่างนี้โปรดทำตามขั้นตอนเหล่านี้:
หลังจากทำตามขั้นตอนเหล่านี้คุณควรพร้อมที่จะเรียกใช้แอปพลิเคชันเว็บสาธิต คุณสร้างฐานข้อมูลที่มีสองแอปพลิเคชันและผู้ใช้สำหรับแต่ละแอปพลิเคชัน
เมื่อคุณเริ่มต้นแอปพลิเคชันเว็บคุณสามารถเข้าสู่แต่ละแอปพลิเคชันได้โดย specyfing ชื่อแอปพลิเคชัน (โดเมน) ตามด้วย backslash และชื่อผู้ใช้ แน่นอนว่าต้องใช้รหัสผ่านของผู้ใช้เช่นกัน
การควบคุมการเข้าสู่ระบบที่เราสร้างขึ้นดูแลส่วนที่เหลือและตรวจสอบให้แน่ใจว่าคุณทำงานภายในบริบทแอปพลิเคชันที่ถูกต้อง การโทรที่ตามมาใด ๆ กับไลบรารีสมาชิก ASP.NET จะเรียกผู้ให้บริการสมาชิกที่กำหนดเองเพื่อส่งคืนชื่อแอปพลิเคชันที่ถูกต้องเพื่อให้แน่ใจว่าการโทรเหล่านี้ทำงานภายในบริบทแอปพลิเคชันที่ถูกต้อง
หมายเหตุ : ไฟล์ Web.Config ของเว็บแอปพลิเคชันสาธิตมีความคิดเห็นที่ระบุทุกสิ่งที่คุณต้องทำเพื่อตั้งค่าแอปพลิเคชันอย่างถูกต้อง อย่าลืมตรวจสอบ
บทความนี้แสดงให้คุณเห็นว่าการใช้ระบบสมาชิก ASP.NET สามารถสร้างแอปพลิเคชันพอร์ทัลที่อนุญาตให้ผู้ใช้เข้าสู่ระบบแอพพลิเคชั่นเสมือนจริงได้อย่างไร
กุญแจแรกในการตระหนักถึงสิ่งนี้คือการสร้างผู้ให้บริการสมาชิกที่กำหนดเองซึ่งทำให้แน่ใจว่าคุณทำงานภายในบริบทแอปพลิเคชันที่ถูกต้องโดยการดึงค่าสำหรับคุณสมบัติ ApplicationName จากตำแหน่งที่เก็บข้อมูลที่เชื่อมโยงกับคำขอของแต่ละบุคคล
ด้วยการสร้างการควบคุมการเข้าสู่ระบบที่กำหนดเองซึ่งลงมาจากการควบคุมการเข้าสู่ระบบ ASP.NET มาตรฐานเราสามารถกำหนดแอปพลิเคชันที่ผู้ใช้ต้องการเข้าถึง
ด้วยการห่อหุ้มข้อมูลนี้ในคุกกี้ที่เข้ารหัสเราสามารถระบุแอปพลิเคชันที่ผู้ใช้ต้องการเข้าถึงโดยอัตโนมัติสำหรับคำขอแต่ละคำขอของเขา