تقلل ميزة عضوية ASP.NET من كمية التعليمات البرمجية التي يجب عليك كتابتها لمصادقة المستخدمين وتخزين بيانات الاعتماد الخاصة بهم. لاقتباس MSDN:
"تمنحك عضوية ASP.NET طريقة مدمجة للتحقق من بيانات اعتماد المستخدم وتخزينها. يمكنك استخدام عضوية ASP.NET مع مصادقة النماذج و / أو مع عناصر التحكم في تسجيل الدخول إلى ASP.NET لمصادقة المستخدمين."
يجب تحديد مزود العضوية في ملف تكوين Web.Config. يمكنك استخدام مزودك المخصص أو أحد مقدمي الخدمات الافتراضية الذين يشحنون مع .NET Framework ، مثل مزود SQLMembershipProvider.
يتم تخزين جميع البيانات المتعلقة بالمستخدم في مجموعة من الجداول المستخدمة من قبل نظام عضوية ASP.NET. في معظم الحالات ، ستستخدم مجموعة واحدة من الجداول لكل تطبيق ويب. ومع ذلك ، يمكنك أيضًا إعادة استخدام المجموعة نفسها لتخزين بيانات اعتماد المستخدم لتطبيقات الويب المتعددة. يمكّنك ذلك بشكل فعال من إنشاء تطبيق ويب واحد يعمل كبوابة تتيح لك تسجيل الدخول إلى أحد هذه التطبيقات "الافتراضية" هذه.
لكن هذا غير ممكن خارج الصندوق. لديك بعض العمل أمامك ، قبل أن تتمكن من دعم هذه التطبيقات الديناميكية.
لنبدأ ...
لنبدأ بفحص إدخال web.config التالي:
قائمة 1 - Web.Config 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) لإعداد قاعدة البيانات الخاصة بك.
كما ذكرنا من قبل ، يمكنك تخزين بيانات اعتماد المستخدم لتطبيقات الويب المتعددة في نفس مجموعة الجداول. يقوم كل تطبيق ويب بفصل بيانات المستخدم الخاصة بهم عن طريق تقسيمها ، فيما أسميه ، سياق تطبيق. يتم تعريف سياق التطبيق هذا بواسطة خاصية ApplicationName لمزود العضوية. كما ترون في القائمة 1 اسم التطبيق هو "myapplication".
يستخدم SQLMembershipProvider هذا الإعداد لتحديد السياق الذي يجب أن يعمل فيه ، حيث يمكن الوصول إلى جميع بيانات المستخدم المرتبطة باسم التطبيق هذا من خلال مكتبة عضوية ASP.NET وعناصر التحكم في تسجيل الدخول.
لسوء الحظ ، يتم تعريف هذا الإعداد بشكل ثابت في web.config. لا يمكنك تغييره بسهولة أثناء وقت التشغيل. إذا كنت ترغب في دعم التطبيقات الديناميكية ، فأنت بحاجة إلى طريقة للتحكم في قيمة خاصية ApplicationName الخاصة بالمزود. يكمن الحل في إنشاء مزود عضوية ASP.NET الخاص بك.
يسترجع SQLMembershipProvider القيمة لخاصية ApplicationName الخاصة به من إعدادات التكوين الواردة في ملف web.config. نريد تغيير القيمة التي يعيدها Getter في هذه الخاصية.
عند تسجيل الدخول ، يجب أن يوضح المستخدم نواياه ، وبعبارة أخرى ، يتعين عليه تحديد أي من التطبيقات الافتراضية التي يريد الوصول إليها. لهذا الغرض ، أطلب من المستخدم تحديد اسم المستخدم وكلمة المرور الخاصة به فحسب ، بل أيضًا التطبيق الافتراضي الذي يريد الوصول إليه. من وجهة نظر المستخدم ، أسمي هذا التطبيق الافتراضي ، المجال.
على سبيل المثال ، افترض أنك أنشأت قاعدة بيانات SQL Server تسمى ASPNETMembership التي تحتوي على جداول عضوية ASP.NET. تحتوي قاعدة البيانات هذه على التطبيقات الافتراضية التالية المحددة في جدول ASPNET_APPLICATIONS:
يحتوي كل تطبيق افتراضي على مستخدم يحمل اسم المستخدم "cger". الآن إذا كنت أرغب في تسجيل الدخول إلى تطبيق NorthWind ، فيجب علي إدخال اسم المستخدم الخاص بي باعتباره "NorthWind cgeers". لتطبيق AdventureWorks ، سيكون هذا "AdventureWorks cgeers".
الجزء الذي يسبق اسم المستخدم هو اسم التطبيق أو فيما يتعلق بالمستخدم ، هذا هو المجال الذي يتعين عليه إدخاله لتحديد التطبيق الافتراضي الذي يريد الوصول إليه. يتم فصل المجال واسم المستخدم بواسطة عكسي.
عندما يقوم المستخدم بتسجيل الدخول باستخدام التحكم في تسجيل الدخول إلى ASP.NET ، يتعين علينا استخراج المجال الذي أدخله وتخزينه في موقع يمكن لمزود العضوية المخصص الوصول إلى الوصول إليه. ومع ذلك ، علينا أن نأخذ في الاعتبار أن ASP.NET تعمل في بيئة متعددة مؤشرات الترابط. يتم التعامل مع كل طلب تم استلامه بواسطة ASP.NET بواسطة مؤشر ترابط منفصل. لا يمكننا تخزين المجال في أي مكان فقط ، وقد تكتبه الطلبات الأخرى الواردة. يجب ربطه بطلب واحد.
المكان المثالي لتخزين المعلومات السياقية المرتبطة بطلب فردي هو سياق HTTP الحالي. يتم تغليف هذه المعلومات السياقية بواسطة فئة HTTPContext.
بدء تشغيل Visual Studio وإنشاء حل فارغ جديد يسمى "AspNetDynamicApplications". بعد ذلك ، أضف مشروع مكتبة فئة جديد إلى الحل المسماة "cgeers.web.security". أضف مراجع إلى System.Configuration و System.Web Semblies. سوف ينحدر مزودنا المخصص من 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 ;
}
}
}كما يمكنك أن ترى مزود العضوية المخصص لدينا ينحدر من SQLMembershipProvider الافتراضي ويتجاوز خاصية ApplicationName. نحن لسنا مهتمين بالستر ، فقط مع getter. عندما يقرأ الموفر الخاصية ApplicationName ، فإننا نحصل على مقبض مع سياق HTTP الحالي من خلال استدعاء الخاصية الحالية الثابتة لفئة HTTPContext. يحتوي كائن HTTPContext الذي تم الحصول عليه على خاصية مجموعة مفتاح/قيمة تسمى العناصر. تخزن هذه المجموعة اسم التطبيق في إدخال تم تحديده بواسطة المفتاح "ApplicationName". اسم هذا المفتاح هو شيء عليك تحديده في وقت التصميم.
الآن في كل مرة يحتاج مزود العضوية المخصصة إلى تحديد اسم التطبيق الذي يستدعي خاصية ApplicationName التي تسترد القيمة من سياق HTTP الحالي. يعمل هذا في بيئة ASP.NET المتعددة المرتبات حيث يتم ربط كل طلب بسياق HTTP الخاص به.
الآن وبعد أن نحن مزود عضوية مخصص يسترجع القيمة لخاصية ApplicationName الخاصة به من سياق HTTP للتنظيم ، لا يزال يتعين علينا اكتشاف طريقة لتخزين اسم التطبيق بالفعل في سياق HTTP.
في المرة الأولى التي يحدد فيها المستخدم التطبيق الافتراضي أو المجال الذي يريد الوصول إليه ، هي عندما يقوم بتسجيل الدخول. كما ذكرنا سابقًا ، يتعين على المستخدم إدخال اسم المستخدم في التنسيق <domain><username> . يتعين علينا إنشاء التحكم في تسجيل الدخول الخاص بنا والذي ينحدر من التحكم في تسجيل الدخول إلى ASP.NET. عند مصادقة المستخدم ، نحتاج إلى استخراج المجال الذي تم إدخاله وحفظه في سياق HTTP الحالي.
أضف مشروعًا جديدًا باستخدام قالب مكتبة الفصل إلى الحل الذي يسمى "cgeers.web.ui.webcontrols". أضف المراجع التالية إلى المشروع:
بعد ذلك ، قم بحذف ملف class1.cs الذي تم إنشاؤه تلقائيًا وأضف فئة جديدة تسمى DynamicApplicationsLogin. نظرًا لأن رمز هذه الفئة مطول تمامًا ، فقد اخترت تقسيمه إلى العديد من القوائم. بعد إضافة كل قائمة شرح موجز للرمز.
قائمة 3 - DynamicApplicationsLogin Control خصائص خاصة
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 واثنين من الخصائص الخاصة ApplicationName و baseusername.
نظرًا لأن المستخدم يدخل المجال واسم المستخدم في نفس التحكم في مربع النص ، فإننا نحتاج إلى تقسيم هذه الأجزاء. كما قد تخمن أن خاصية ApplicationName تستخرج المجال ويعيد اسم baseusername اسم المستخدم. على سبيل المثال ، إذا دخل المستخدم NorthWind cgeers ، فإن خاصية ApplicationName سترجع "NorthWind" وستقوم خاصية BaseUserName بإرجاع "cgerers".
قائمة 4 - طريقة التحكم في ديناميكية.
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 الحالي بحيث يمكن لمزود العضوية لدينا استرداد القيمة الصحيحة لخاصية ApplicationName الخاصة به.
أخيرًا وليس آخرًا ، يتم تعيين قيمة خاصية اسم المستخدم على اسم المستخدم فقط من خلال تعيين خاصية BaseUserName لها. يقوم حقل _fullusername الخاص بتخزين القيمة التي أدخلها المستخدم مؤقتًا (المجال username). سترى كيف يتم استخدام هذا الحقل لاحقًا.
بعد تخزين اسم التطبيق في سياق HTTP ، تحتوي خاصية اسم المستخدم فقط على اسم المستخدم الذي يسمى تطبيق الأساس ، وهذا يتسبب في التحقق من صحة اسم المستخدم داخل سياق التطبيق الصحيح.
قائمة 5 -DynamicApplicationsLogin Control طريقة onloginerror
protected override void OnLoginError ( EventArgs e )
{
UserName = _fullUserName ;
base . OnLoginError ( e ) ;
}تجاوز طريقة onloginerror وقبل الاتصال بالتنفيذ الأساسي ، قم بتعيين حقل _fullusername إلى خاصية اسم المستخدم. عند مصادقة المستخدم (طريقة onauthenticate) ، يجب أن تحتوي خاصية اسم المستخدم على اسم المستخدم فقط وليس المجال ، ولكن عندما تفشل المصادقة ، تحتاج إلى التأكد من أن النص الذي أدخله المستخدم في مربع النص الذي يمثل اسم المستخدم يتم إعادة ضبطه على القيمة التي أدخلها المستخدم في البداية. بخلاف ذلك ، قد يكون الأمر مربكًا للمستخدم إذا اختفى المجال الذي أدخله.
قائمة 6 - طريقة التحكم في DynamicApplicationsLogin
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 لـ FormauthenticationTicket. يتم استخدام تذكرة المصادقة هذه بواسطة مصادقة النماذج لتحديد مستخدم مصادق. نحن هنا نقوم بتخزينها في ملف تعريف الارتباط وإضافتها إلى استجابة سياق HTTP الحالي. في وقت لاحق ، سترى لماذا هذا مطلوب.
يمكنك إلقاء نظرة على القائمة 6 ، سترى أن ملف تعريف الارتباط الذي يحتوي على تذكرة مصادقة النماذج يتم إنشاؤه بواسطة فئة مساعدة تسمى FormauthenticationHelper. هذه فئة مساعدة ثابتة تحتوي فقط على طريقة واحدة ، وهي StoruserDatainauthenticationCookie.
أضف فئة جديدة تسمى FormsAuthenticationHelper إلى مشروع CGEERS.WEB.Security وأضف الكود الموضح في القائمة 7.
قائمة 7 - FormauthenticationHelper
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 ;
}
}تقوم طريقة StoreSerDataInauthenticationCookie (...) باسترداد ملف تعريف الارتباط للمستخدم المحدد (معلمة اسم المستخدم) التي تحتوي على تذكرة مصادقة النماذج. بعد ذلك ، يتم فك تشفير ملف تعريف الارتباط من أجل الوصول إلى كائن FormsAuthenticationTicket. بعد ذلك ، يتم إنشاء 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 مع معالج أحداث DETINEAPLICATIONNAME.
يتحقق DETINAPLICATIONNAMENAME (...) معالج الأحداث إذا كان يتعامل مع طلب مصادق عليه ، وإذا كان الأمر كذلك ، فإن ذلك يسترجع تذكرة الرسائل التي تم إرسالها من قبل العميل.
تحدد هذه التذكرة سياق التطبيق الذي يعمل فيه. يتم استخراج اسم التطبيق من التذكرة باستخدام طريقة getAppLicationName () من FormauThenticationTicket. هذه طريقة تمديد ، سأقوم بمعالجتها في القسم التالي.
أخيرًا بعد استخراج اسم الطلب من التذكرة ، يتم تخزينه ضمن سياق HTTP حتى يتمكن مزود العضوية المخصص لدينا.
أضف فئة جديدة تسمى FormsAuthenticationTicketextensions إلى مشروع CGEERS.WEB.Security وأضف الكود الموضح في القائمة 9.
قائمة 9 - FormauthenticationTicketextensions
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 الخاصة بـ FormauthenticationTicket من خلال تسبقه ببادئة "an =". وبالتالي ، تحتاج طريقة التمديد هذه إلى أخذ هذا في الاعتبار عند استرداد اسم التطبيق من FormauThenticationTicket.
ملاحظة : لا تتردد في تحسين الطريقة التي يتم بها تخزين اسم التطبيق داخل التذكرة ، ولكن تذكر تنفيذ نفس النظام للتحكم في DynamicApplicationsLogin وطريقة التمديد هذه.
على غرار التحكم في DynamicApplicationsLogin ، قمت بإنشاء عناصر تحكم تنحدر من ASP.NET PasswordRecovery و ChangePassword. إذا كنت تريد أن يتمكن المستخدم من استرداد كلمة المرور الخاصة به و/أو تغييره ، فأنت بحاجة إلى استخدام عناصر التحكم هذه. يتأكدون من تنفيذ كل شيء في سياق التطبيق الصحيح.
يتشابه التنفيذ إلى حد كبير مع التحكم في DynamicApplicationsLogin ، لذلك لن أدرج رمز عناصر التحكم هذه هنا. إذا كنت ترغب في التحقق من الكود المصدري لعناصر التحكم هذه ، فقم بتنزيل رمز المصدر المصاحب لهذه المقالة. يمكنك العثور على هذه الضوابط في مشروع cgeers.web.ui.webcontrols.
يحتوي الكود المصدري المصاحب لهذا المقال أيضًا على مشروع تطبيق ويب تجريبي يوضح DynamicApplicationsSqlMembershipProvider ، وعناصر التحكم في تسجيل الدخول الجديدة ، ووحدة HTTP المخصصة الخاصة بنا ... وما إلى ذلك.
الشكل 2 - حل Visual Studio

من أجل تشغيل هذا التطبيق التجريبي ، يرجى اتباع هذه الخطوات:
بعد اتباع هذه الخطوات ، يجب أن تكون مستعدًا لتشغيل تطبيق الويب التجريبي. قمت بإنشاء قاعدة بيانات تحتوي على تطبيقين ومستخدم لكل تطبيق.
عند بدء تشغيل تطبيق الويب ، يمكنك تسجيل الدخول إلى كل تطبيق عن طريق تحديد اسم التطبيق (المجال) متبوعًا بخلفي واسم المستخدم. طبعا كلمة مرور المستخدم مطلوبة أيضا.
تحكم تسجيل الدخول الذي أنشأناه في الاعتناء بالباقي وتأكد من أنك تعمل في سياق التطبيق الصحيح. أي مكالمات لاحقة مع مكتبة عضوية ASP.NET ستؤدي إلى تشغيل مزود العضوية المخصص لإرجاع اسم التطبيق الصحيح وبالتالي التأكد من أن هذه المكالمات تعمل في سياق التطبيق الصحيح.
الملاحظة : يحتوي ملف Web.Config الخاص على تطبيق الويب التجريبي على تعليقات تحدد كل ما تحتاج إلى القيام به من أجل إعداد التطبيق بشكل صحيح. تأكد من التحقق من ذلك.
أوضحت لك هذه المقالة كيف يمكن استخدام نظام عضوية ASP.NET لإنشاء تطبيق بوابة يسمح للمستخدمين بتسجيل الدخول إلى أحد التطبيقات الافتراضية العديدة.
المفتاح الأول لإدراك ذلك هو إنشاء موفر عضوية مخصص يتأكد من تشغيله في سياق التطبيق الصحيح عن طريق استرداد قيمة خاصية ApplicationName من موقع تخزين مرتبط بطلب فردي.
من خلال إنشاء عنصر تحكم تسجيل دخول مخصص ينحدر من التحكم في تسجيل الدخول إلى ASP.NET القياسي ، يمكننا تحديد التطبيق الذي يريد المستخدم الوصول إليه.
من خلال تغليف هذه المعلومات في ملف تعريف ارتباط مشفر ، يمكننا تحديد التطبيق تلقائيًا الذي يريد المستخدم الوصول إليه لكل طلب من طلباته.