• 1
Robatic

Membership Authentication & Roles Authorization

سؤال

السلام عليكم ورحمة الله وبركاته

تقريبا في الأسبوعين السابقين كان في أسئلة من قبل الأعضاء حول موضوع المستخدمين وتخزين كلمات مرورهم وتحديد كم طول كلمة المرور وكم الحد الأدنى للأرقام في كلمة المرور والحد الأدنى للحروف الخاصة وما إلى ذلك. أولا خلونا نتفق على بعض المسطلحات عشان نكون كلنا في إتجاه واحد. عملية تخزين المستخدمين بكلمات مرورهم في الـ ASP.NET تسمى بالـ Membership، بينما عملية تسجيل دخول المستخدم والتأكد من كلمة المرور تسمى بالـ Authentication. أما عملية تقسيم المستخديمن إلى مجموعات (مثلا المشرفين، المدراء، المراقبين .... إلخ) تسمى بالـ Roles، عملية السماح أو عدم السماح لمستخدم معين بالوصول إلى مصدر معين بناء على الـ Roles الذي ينتمي إليه أو إليهم تسمى بالـ Authorization. الشخص الذي لا يمتلك اسم مستخدم يسمى بالـ Anonymous User.

أولا : ما هي أنواع الـ Authentication في الـ ASP.NET :

عندما تقوم بإنشاء مشروع جديد عن طريق VS 2005/2008 وتقوم بتحديد المشروع على أنه ASP.NET website لاحظ أنه سيتم إضافة ملف خاص بإسم web.config، بداخله ستلاحظ العبارة أو الإدخال التالي :


<system.wbe>
.
.
.
<authentication mode="Windows" />
.
.
.
</system.web>

هذا هو الإدخال الذي من خلالة تقوم بتحديد طريقة أو نوع الـ Authentication لمشروعك وكما نرى في حالتنا هذه أنه بشكل إفتراضي يكون Windows. والمقصود هنا اسم المستخدم الذي دخلت به في نظام MS Windows (أي أن عملية تسجيل الدخول والتحقق من كلمة المرور ستكون عن طريق نظام تشغيل Windows الموجود في الجهاز الحالي الذي عن طريقة ستقوم بتصفح هذه الصفحة أو الموقع). فلو قمنا بتغيير هذا النوع سنلاحظ أن VS 2005/2008 سيقوم بإقتراح Windows, Forms, Passport, None. حيث أن Windows سبق شرحه أعلاه، و Passport لم أستخدمها قط ولكن مما قرأت يقال أن هناك ما يسمى بالـ Microsoft's Passport Service وهي ستكون مسؤولة عن التحقق من اسم المستخدم وكلمة المرور، أما None فهي كلمة معبرة عن نفسها ولاتحتاج إلى شرح، وأخيرا وليس آخرا Forms وهذا ما سوف نتطرق إليه بعد قليل.

ملاحظة : عملية التحقق من إسم المستخدم وكلمة المرور تسمى بالـ Authentication Formalities.

Forms Authentication :

من منا لم يستخدم الـ Forms Authentication ، عندما تقوم بتسجيل الدخول في هذا المنتدى أو في تسجيل الدخول لبريدك الإلكتروني أو لحسابك البتكي والأمثلة كثيرة. بكل بساطة الـ Forms Authentication عبارة عن القيام بـ Authentication Formalities عن طريق HTML Form بحيث (في أبسط صورة) يوجد هناك حقلين أحدهما لإسم المستخدم والثاني لكلمة المرور.

ثانيا : تطبيق Forms Authentication على مشروعك

يمكنك فعل ذلك بعدة ضغطات بالفأرة عن طريق إستخدام ASP.NET Website Administration Tool (AWAT), plain & simple. هنا لن نتطرق لهذه الطريقة ولكن سنقوم بتحديد ما يترتب على ذلك فقط. عندما تقوم بإستخدام AWAT ستلاحظ أن هناك خطوات أو Wizard من خلالها ستتمكن من تجهيز موقعك، وتشمل هذه الخطوات تحديد نوع الـ Authentication وكم طول كلمة المرور، وهل البريد الإلكتروني يتكرر أم لا، وهل فرض إستخدام السؤال السري وما هو وما هي الإجابات المحتملة و و و و. بعد أن تنتهي من تحديد ما سبق وبعد أن تقوم بإدخال بعض المستخدمين والـ Roles عن طريق AWAT ستلاحظ أن هناك مجلد App_Data تم إضافة في مشروعك وبداخله ملف aspnetdb.mdf، قم بفتح الملف ستلاحظ أن AWAT قد قام ببناء قاعدة بينات كاملة ومتكاملة وصدقني أنه يمكنك الإعتماد عليها جدا حيث أنه ستلاحظ أن كلمات المرور وبعض البيانات المهمة قد تم تشفيرها داخل جداول قاعدة البيانات aspnetdb.mdf. بعد ذلك قم بإستخدام الأدوات الجاهزة والخاصة بالـ Authentication مثل LoginControl ومل إلى ذلك.

سؤال : ماذا لو كانت عندك قاعدة بينات ولنفرض أنها MS SQL - حيث لا تكون هناك مشكلة في التوافق - وأنت تريد إضافة الجداول الموجودة في aspnetdb.mdf إلى قاعدة بياناتك بدل من أن يتم إضافتها في ملف خارجي ؟

طبعا قد يسأل شخص وما الضرر في أن تكون الجداول المتعلقة بالـ Authentication مفصولة، ستكون الإجابة هي كالتالي : في كل مرة مشروعك يحتاج إلى أداء أي شيء متعلق بالـ Authentication سيقوم بالإتصال بملف الـ aspnetdb.mdf، وفي كل مرة يحتاج أن يقوم بأي شيء يتعلق بالـ business الذي يقوم به سوف يتصل بقاعدة البيانات التي بها الجداول المتعلقة بالـ business الذي بسببة تم إنشاء هذا المشروع، فهناك قاعدتي بيانات فقد يرغب الشخص بتغيير السؤال إلى : لماذا لا يكون هناك مركزية لقاعدة البيانات. عموما بناء الجداول المتعلقة بالـ Authentication داخل قاعدة بينات موجودة مسبقا بسيط جدا كل ما تحتاج إليه هو فقط إستخدام ASP.NET SQL Server Registration Tool عن طريق الذهاب إلى المجلد الذي تم تثبيت الـ dot Net Framework وكتابة الأمر aspnet_regsql بإستخدام الـ command-line كما هو موضح أدناه


%WINDOWS%\Microsoft.NET\Framework\<your .net framework version>\aspnet_regsql

بعد ذلك سيظهر لك wizard قم بإتباعها إلى النهاية وسيتم بناء الجداول داخل قاعدة البيانات التي تم تحديدها بإستخدام الـ wizard.

سؤال : ماذا لو كان هناك جداول خاصة بك أو بمشروعك تحوي على معلومات الـ Authentication وتريد إستخدامها بدل من الجداول التي سيتم بنائها عن طريق AWAT أو aspnet_regsql، ماذا لو كانت الجداول الناتجة عن كل من AWAT و aspnet_regsql أكثر من اللازم لمشروعك أو أنك فقط تريد تطبيق نظام Authentication بسيط جدا ؟ ماذا لو كانت قاعدة البيانات الموجودة Oracle أو MySql أو شيء غير MSSQL، بمعنى آخر ماذا لو ان الأداة aspnet_regsql لا تفيدك ؟

ثالثا : A simple Authentication System

هنا سنقوم ببناء نظام الـ Authentication الخاص بناء وسوف نحاول أن نجعله بسيط جدا، سنقوم ببناء بعض الجداول المتعلقة بموضوعنا هذا إبتداء بجدول المستخدمين وإنتهاء بالجدول الخاص بالـ Roles، فكل خطوة سنقوم بها سأقوم بكتابة تركيب الجدول الذي نحتاجة.

المستخدمين users_tbl: سنقوم ببناء جدول المستخدمين (users_tbl) كما هو موضح أدناه :


create table users_tbl (
uid int primary key identity(1,1),
uname varchar(50),
password varchar(10),
email varchar(50)
)

إضافة الإعدادات اللازمة في ملف web.config :

المقصود هنا تحديد نوع الـ Authentication وعنوان الصفحة التي سيتم توجيه الـ anonymous user إليها في حالة تطلب تسجيل الدخول للوصول لمصدر معين (سنرى هذه العملية لاحقا) وأيضا الصفحة الإفتراضية التي سيتم توجيه المستخدم إليها بعد أن تتم عملية الـ Authentication Formalities، بشكل إفتراضي ستكون صفحة تسجيل الدخول هي login.aspx ولكن يمكنك تغيير ذلك، قم بإضافة التالي في ملف web.config :


<system.web>
.
.
.
<authentication mode="Forms">
<forms loginUrl="~/login.aspx" defaultUrl="~/Default.aspx" />
</authentication>
.
.
.
</system.web>

بناء class يساعدنا في عملية Authentication Formatlities وتسجيل المستخدمين "Utilities.cs" :

قم بإضافة مجلد خاص عن طريق الضغط بالزر اليمين على الـمشروع ومن ثم Add ASP.NET Folder ومن ثم App_Code وبعد ذلك قم بإضافة class بإسم Utilities.cs داخل App_Code وبعد ذلك قم بكتابة التالي :


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;

/// <summary>
/// Summary description for Utilities
/// </summary>
public static class Utilities
{
// Make sure to change the connectionString to your relating MDF file
private const string connectionString =
@"data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|mydb.mdf;User Instance=true";

// Note: Exceptions are not handled in any of the following codes, try to handle them the way
// you see fit

public static void RegisterNewUser(string username, string password, string email)
{
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(@"insert into users_tbl(uname, password, email)
values(@uname, @password, @email)", con);

// Note: do not use OledbParameters.AddWithValue with complex data type (image, blob, date, binary ... etc)
cmd.Parameters.AddWithValue("uname", username);
cmd.Parameters.AddWithValue("password", password);
cmd.Parameters.AddWithValue("email", email);

con.Open();
cmd.ExecuteNonQuery();
}
}
}

بناء صفحة لتسجيل المستخدمين "register.aspx" :

أعتقد أن اسم الصفحة يصف مهمتها، بم بإضافة صفحة بإسم register.aspx بالشكل التالي :


<h3 style="text-align: center">
Register New Account</h3>
<table border="0" cellpadding="5px" cellspacing="0" style="width: 350px; border: 1px dashed #07f;
border-collapse: collapse; margin: 0 auto;">
<tr>
<td>
User Name
</td>
<td>
<asp:TextBox ID="usernameTextBox" MaxLength="50" runat="server" />
<asp:RequiredFieldValidator ID="usernameRequiredFieldValidator" runat="server" Text="*"
ErrorMessage="You must provide a username!" ControlToValidate="usernameTextBox" />
</td>
</tr>
<tr>
<td>
Password
</td>
<td>
<asp:TextBox ID="passwordTextBox" MaxLength="10" runat="server" TextMode="Password" />
<asp:RequiredFieldValidator ID="passwordRequiredFieldValidator" runat="server" Text="*"
ErrorMessage="You must provide a password!" ControlToValidate="passwordTextBox" />
</td>
</tr>
<tr>
<td>
Retype Password
</td>
<td>
<asp:TextBox ID="retypePasswordTextBox" MaxLength="10" runat="server" TextMode="Password" />
<asp:CompareValidator ID="passwordCompareValidator" runat="server" Text="*" ErrorMessage="Password doesn't mathc!"
ControlToValidate="retypePasswordTextBox" ControlToCompare="passwordTextBox"
Operator="Equal" />
</td>
</tr>
<tr>
<td>
E-Mail
</td>
<td>
<asp:TextBox ID="emailTextBox" MaxLength="50" runat="server" />
<asp:RegularExpressionValidator ID="emailRegularExpressionValidator" runat="server"
ControlToValidate="emailTextBox" Text="*" ErrorMessage="Your email is not in a correct form!"
ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" />
</td>
</tr>
<tr>
<td>
 
</td>
<td style="text-align: right;">
<asp:Button ID="saveButton" runat="server" Text="Register" OnClick="saveButton_Click" />
</td>
</tr>
<tr>
<td>
 
</td>
<td>
<asp:Label ID="statusLabel" runat="server" Text="" ForeColor="Green" />
</td>
</tr>
<tr>
<td colspan="2">
<asp:ValidationSummary ID="registeringValidationSummary" runat="server" />
</td>
</tr>
</table>


/****************************************
saveButton_Click handler
****************************************/

protected void saveButton_Click(object source, EventArgs e)
{
Utilities.RegisterNewUser(usernameTextBox.Text, passwordTextBox.Text, emailTextBox.Text);
statusLabel.Text = string.Format("Thank you '{0}' for your registration.", usernameTextBox.Text);
}

إضافة صفحة تسجيل الدخول "login.aspx" :

هذه الصفحة لا تحتاج إلى شرح، ولكن قبل أن نضيفها أود أن أخبركم بأنه لن نستخدم الـ Login Control الموجود في الأدوات بل سنستخدم فقط TextBox للقيام بعملية الـ Authentication Formalities، ولكن قبل ذلك يجب أن نضيف AuthenticateUser Method في الـ Utilities Clss والغرض منها هو القيام بعملية الـ Authentication Formalities، كما هو موضح في التالي :


public static bool AuthenticateUser(string username, string password)
{
bool isAuthenticated = false;

using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(
"select count(uname) from users_tbl where uname=@uname and password=@password",
con);

cmd.Parameters.AddWithValue("uname", username);
cmd.Parameters.AddWithValue("password", password);

con.Open();

isAuthenticated = int.Parse(cmd.ExecuteScalar().ToString()) == 1;
}

return isAuthenticated;
}

الآن سنقوم بإنشاء صفحة الـ login.aspx وسوف نرى كيفية إستخدام System.Web.Security.FormsAuthentication.RedirectFromLoginPage حيث أنها ستقوم بتسجيل cookie في متصفح المستخدم يدل على أن هذا المستخدم تم المصادقة عليه وبعد ذلك سيتم إعادة توجيهه إما إلى الصفحة التي تطلب فيها تسجيل الدخول (أي كانت خاصة بحيث لا يدخلها من ليس له حساب أو من يجب أن ينتمي إلى مجموعة أو Role معين، سوف نراى ذلك لاحقا)، أو إلى الصفحة الإفتراضية التي تم تحديدها في ملف web.config في العنصر authentication، كما هو موضح في الكود التالي :


<h3 style="text-align: center">
Login</h3>
<table border="0" cellpadding="5px" cellspacing="0" style="width: 350px; border: 1px dashed #07f;
border-collapse: collapse; margin: 0 auto;">
<tr>
<td>
Username
</td>
<td>
<asp:TextBox ID="usernameTextBox" MaxLength="50" runat="server" />
<asp:RequiredFieldValidator ID="usnernameRequiredFieldValidator" runat="server" Text="*"
ErrorMessage="Please provide a username!" ControlToValidate="usernameTextBox" />
</td>
</tr>
<tr>
<td>
Password
</td>
<td>
<asp:TextBox ID="passwordTextBox" MaxLength="10" runat="server" TextMode="Password" />
<asp:RequiredFieldValidator ID="passwordRequiredFieldValidator" runat="server" Text="*"
ErrorMessage="Please provide a password!" ControlToValidate="passwordTextBox" />
</td>
</tr>
<tr>
<td>
 
</td>
<td style="text-align: right;">
<asp:Button ID="loginButton" runat="server" Text="Login" OnClick="loginButton_Click" />
</td>
</tr>
<tr>
<td>
 
</td>
<td style="text-align: right;">
<a href="register.aspx">Not registered? What are you waiting for ?</a>
</td>
</tr>
<tr>
<td>
 
</td>
<td>
<asp:Label ID="errorLoginLabel" runat="server" runat="server" ForeColor="Red"
Text="No such user is found or invalid password" Visible="false" />
</td>
</tr>
<tr>
<td colspan="2">
<asp:ValidationSummary ID="loginValidationSummary" runat="server" />
</td>
</tr>
</table>

/****************************************
loginButton_Click handler
****************************************/

protected void loginButton_Click(object source, EventArgs e)
{
if (Utilities.AuthenticateUser(usernameTextBox.Text, passwordTextBox.Text))
FormsAuthentication.RedirectFromLoginPage(usernameTextBox.Text, false);
else errorLoginLabel.Visible = true;
}

طبعا لو تلاحظوا الـ System.Web.Security.FormsAuthentication.RedirectFromLoginPage تاخذ two arguments الأولى عبارة عن إسم المستخدم الي راح يصدر له Cookie اما الثانية فهي قيمة بولينية لو true معناته إن الـ cookie راح تكون دائمة أو ثابته "Persistence"، لو كان false فمعناته راح تنتهي "expire" الـ cookie بمجرد ما يقوم المستخدم بإغلاق المتصفح، لاحظوا إننا أرسلنا الـ argument الثاني بقيمة false ويعود السبب إلى إمكانية حفظ الـ cookie لمدة 50 سنة (can you believe that crap!!!!) وهذا قد يولد ثغرة إمكانية التنصت أو أخذ الـ cookie وبالتالي راح نخسر الـ privacy factor.

إضافة LoginName Control في الصفحة "Default.aspx" :

سوف نقوم بإضافة LoginName Control في الصفحة المذكورة أعلاة فقط لنرى هل سوف تقوم الـ ASP dotNet فعلا بتسجيل cookie وبالتالي ظهور اسم المستخدم أم لا، ,وأيضا سوف نستخدم الـ LoginStatusControl وهو يقوم بعرض رابط إما تسجيل الدخول أو تسجيل الخروج على حسب حالة المستخدم الذي يتصفح الصفحة ، قم بكتابة التالي :


<h3 style="text-align: center;">
Default.aspx
</h3>
<p>
<asp:LoginName ID="loginName" runat="server" FormatString="Welcome '{0}'" />
</p>
<asp:LoginStatus ID="loginStatus" runat="server" LoginText="Click here to login"
LogoutText="Click here to logout" />
<br />
<a href="register.aspx">Not registered? What are you waiting for ?</a>

لاحظوا أن الـ LoginStatus سيقوم بقراءة الإعدادات من ملف web.config والمقصود بها صفحة تسجيل الدخول والصفحة الإفتراضية التي سيعاد توجيه المستخدم إليها بعد تسجيل الخروج

بعد كل ما تم شرحه بقي علينا أن نرى كيفية إضافة Roles وكيفية تحديد مستوى الوصل إلى بعض موارد الموقع إما على حسب حالة المستخدم (Authenticated / Anonymous) أو على حسب أي Role ينتمي إليه المستخدم. بإذن الله سنكمل في الدرس القادم.

أتمنى أن أكون قد أصبت في قولي وأن يكون شرحي واضح وموجزوأيضا أتمنى لكم التوفيق.

مرفق المشروع الذي أستند عليه في شرحي هذا

ألهم أرزقنا جميعا علما نافع غير ضار ولا تحرمنا جنانك ورؤية الأبرار، الهم آمين

MembershipAndRoles.zip

8

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

22 إجابة على هذا السؤال .

  • 0

مشكور صديقي والله يجزيك كل خير

لديي استفسار

هو اي الطريقتين

فصل قاعدة البيانات الخاصة بالتحققق ووو

عن قاعدة بيانات المشروع

ام دمجهما بملف واحد

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بارك الله فيك وفي علمك

تحياتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

شرح جميل .. جزاك الله كل خير

1

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم ورحمة الله وبركاته

أشكر أخواني الكرام على مرورهم الكريم

بالنسبة لأخي AsJsGle بصراحة لم أفهم ما هو المطلوب، ولكن لو كنت تقصد أي الطريقتين أفضل إما دمج قاعدتي البيانات أو فصلها ستكون الإجابة : على حسب وضعك الحالي، لا يمكننا أن نعمم شيء معين فقد تكون هناك حالات تشذ عن قاعدة معينه، ولكن لي تعقيب بسيط في موضوع قاعددتي بيانات منفصله، لاحظ لو كان هناك أكاود أو DAL معين للقيام بوظائف الموقع فهذا يعني أنك ستضطر إلى بناء DAL أخرى للقايم بعملية الـ Authentication & Authorization، بمعني آخر سيكون لديك two ConnectionStrings، في الأخير هناك مثل شعبي يقول "كل ينام على الجمب الي يريحه" ولا ننسى أن الإختلاف في وجهات النظر لا يفسد في الود قضيه :wink:

دعونا نكمل، الآن رأينا كيفية إنشاء نظام Authentication بإستخدام AWAT و بطريقتنا الخاصه، ورأينا ماهي الإعدادات اللازمة التي يجب إضافتها في ملف web.config، ورأينا كيفية إستخدام System.Web.Security.FormsAuthentication.RedirectFromLoginPage في حالة عدم إستخدام الـ LoginControl، وأيضا تأكدنا من إنشاء الـ Cookie الخاصة التي بداخلها بيانات المستخدم الحالي عن طريق عرض اسم المستخدم في الـ LoginName Control، بقي علينا أن نرى كيفية التعامل مع الـ Roles و Authorization.

أولا : بناء جدولين roles_tbl و users_roles_tbl :

حيث أن جدول roles_tbl سيحوي الـ Roles الموجوده في نظامنا و جدول users_roles_tbl هو الجدول الذي يربط ما بين المستخدمين users_tbl و roles_tbl عن طريق الـ PK الموجود في كلا الجدولين، كما هو مبين في الـ diagram التالي :

post-91978-12730443423438_thumb.jpg

ثانيا : كيفية أخذ الـ Roles الذي ينتمي إليها مستخدم معين

ستتم هذه المرحله عن طريق جزئين، الأول عن طريق إستخلاص الـ Roles الذي ينتمي إليها مستخدم معين من قاعدة البيانات، والثانية عن طريق إضافتها إلى الـ Cookie التي يستخدمها الـ ASP.NET لتخزين بيانات هذا المستخدم.

إستخلاص الـ Roles من قاعدة البيانات :

سنقوم بإضافة GetUserRoles Method إلى الـ Utilities Class المعرف مسبقا في المجلد الخاص App_Code كما هو موضح أدناه :


public static string[] GetUserRoles(string username)
{
List<string> roles = new List<string>();

using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(
@"select role_name
from roles_tbl r, users_tbl u, users_roles_tbl ur
where u.uname = @username and u.uid = ur.uid and r.role_id = ur.role_id", con);

cmd.Parameters.AddWithValue("username", username);

con.Open();

using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
roles.Add(reader["role_name"].ToString());
}
}

return roles.ToArray();
}

لاحظوا أن نوع البيانات المرجعه من GetUserRoles هي عبارة عن string[]، سوف نرى سبب ذلك الآن.

إضافة الـ Roles إلى الـ Cookie الخاصة ببيانات المستخدم :

نقوم بذلك عن طريق ما يعرف بـ IPrincipal حيث أنها عبارة عن Interface مسؤلة عن البيانات الأمنية الخاصة بمستخدم معين أو Request معين، ولحسن حظنا هناك Class جاهز يقوم بعمل Implement للـ IPrincipal وهو System.Security.Principal.GeneralPrincipal، لماذا سنقوم بذلك ؟ عندما تقوم بكتابة HttpContext.Current.User ألقي نظرة على التلميحات التي سيقدمها لك VS 2005/2008، ستلاحظ أن نوع الـ HttpContext.Current.User هو عبارة عن IPrincipal، وعندما نقوم ببناء instance من System.Security.Principal.GeneralPrincipal ستلاحظ أن الـ Constructor يأخذ two Arguments الأولى من نوع IIdentity وهي عبارة عن الـ Identity الخاصة بالمستخدم الحالي (أذا كان Authenticated) والثانيه عبارة عن الـ Roles التي ينتمي إليها هذا المستخدم وهي من نوع string[]. نطرح السؤال التالي : متى نقوم بهذه العملية ؟ هل نقوم بها في الـ Page_Load Handler ؟ أم بعد ما يتم التحقق (Authentication Formalities) ؟ سأجيب على السؤالين بالسؤال التالي : بما أن عملية إضافة الـ Roles تتم على المستخدم الحالي إذا كان Authenticated، ماذا سيحدث لو كان هذا المستخدم أساسا Unauthenticated ؟

نقوم بحل هذه المشكلة عن طريق إضاقة ملف خاص يعرف بـ Global.asax حيث أنه يحوي على Event Handlers على مستوى الـ Server والـ Application، وعن طريق الـ Event Handlers الخاصه بالـ Application سوف نقوم بإضافة Application_AuthenticateRequest Handler حيث أنها سوف تتنفذ في كل صفحة يتم فيها Authentication & Authorization. بعد ما تقوم بإضافة Global.asax عن طريق الضغط بالزر اليمين على إسم المشروع ومن ثم Add New Item قم بكاتبة الكود التالي في ملف Global.asax :


protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(
User.Identity, Utilities.GetUserRoles(User.Identity.Name));
}
}

ثالثا : تحديد مستوى الوصول Authorization:

يتم ذلك على مستوى المجلد بحيث أنه لو كانت هناك صفحة خاصة بالـ Admins فينبغي عليك وضعها داخل مجلد منفصل ومن ثم إضافة web.config file لهذا المجلد ومن ثم كتابة بعض الإعدادات، مثلا لو أردنا أن تكون صفحة معينه page داخل مجلد معين folder لا يتم عرضها إلا من قبل الـ Authenticated Users سيكون ملف الـ web.config داخل هذا المجلد بالشكل التالي :


<?xml version="1.0"?>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>

<authorization>
<deny users="?"/>
</authorization>

</system.web>
</configuration>

حيث أن الرمز ؟ على مستوى الـ Users يقصد به الـ Unauthenticated Users والرمز * يقصد به الـ Authenticated Users، يمكنك أيضا منع مستخدم معين عن طريق اسم المستخدم، وفي حالة وجود أكثر من مستخدم تستطيع أن تكتبهم وتفرق بينهم بفواصل ",". أما لو أردنا أن تكون الصفحة حكرا على المستخدمين الذين ينتمون إلى الـ Admin Role سيكون ملف web.config بهذا الشكل :


<?xml version="1.0"?>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>

<authorization>
<allow roles="Admin"/>
<deny users="?, *"/>
</authorization>

</system.web>
</configuration>

أيضا يمكنك إضافة أكثر من Role عن طريق فصلهم بفواصل "," سواء منع أو سماح الوصول.

ملاحظة : غند كتابة كل من allow & deny قد تكون النتيجة غير متوقعه، مثلا قد ينمع مستخدم معين من دخول الصفحة والمفروض عدم حصول ذلك أو يسمح لمستخدم دخول صفحة وهو لا يحق له ذلك، وقد يكون السبب هو كتابة الـ allow & deny بشكل خاطئ، لتفادي ذلك أعتبر أن كلا من allow & deny عبارة عن if else بحيث أنه لو توفر الجزء الأول لن ينفذ الجزء الثاني. فمثلا لو كان الـ web.config بهذا الشكل :


<?xml version="1.0"?>
<!--
Note: As an alternative to hand editing this file you can use the
web admin tool to configure settings for your application. Use
the Website->Asp.Net Configuration option in Visual Studio.
A full list of settings and comments can be found in
machine.config.comments usually located in
\Windows\Microsoft.Net\Framework\v2.x\Config
-->
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>

<authorization>
<allow users="*" roles="Admin"/>
<deny users="?"/>
</authorization>

</system.web>
</configuration>

سيتم السماح بالدخول لكل مستخدم قد تم تسجيل دخوله بغض النظر عن الـ Role ال1ي ينتمي إليه.

في المثال المرفق قد قمت بإضافة two Roles وهما Admin, Client وقد أضفت مستخدم بإسم وكلمة مرور Robatic وينتمي إلى الـ Admin Roles وأيضا مستخدم بإسم وكلمة مرور X_Client وينتمي إلى Client Role، وأضفت أيضا ثلاث صفحات هي

admin/Default.aspx لا يدخلها إلى من هم في Admin Roles و client/Default.aspx لا يدخلها إلا من هم في Client Role و auth_users/Default.aspx لا يدخلها إلا من هم Authenticated Users.

في الأخير هذه الطريقة ليست إلا مجرد محاولة لتوضيح ماذا يحدث ولتعطيك فقط نظرة أولى لعملية الـ Membership Authentication & Role Authorization، والذين يريدون أن يقوموا بما هو أكثر وأئمن وأفضل عليهم البحث في موضوع Member Provider & Role Provider حيث يتم فيه وراثة وإعادة تعريف الـ Classes الخاصة بهذه العملية لما يليق بوضعهم الحالي.

ملاحظة أخيره : ممكن لمستخدم معين أن ينتمي لأكثر من Role (جل من لا يسهو)

أتمنى للجميع التوفيق

MembershipAndRoles.zip

تم تعديل بواسطه Robatic
2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

قمت بتثبيت الموضوع بعد إذن مشرف القسم

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

ألسلام عليكم ورحمة الله وبركاته ,,,

شكرا لك Robatic على الموضوع .. أخي أنا قرات الموضوع وأتبعت نفس الخطوات لعمل نفس المثال

شغلت مثال ولم تظهر أي رسالة خطأ ، تتبعت سير البيانات ولم يظهر أي يخطأ يتم التأكد من البيانات أثناء عملية تسجيل الدخول وإعطائه صلاحية الــ ROLE

في حال كان Admin أو USER ولكن المشكلة هي بعد التاكد من مدير النظام وإعطائه الصلاحيات كل ما حاولت أن ادخل إلى Folder الـــ Admin يتم إرجاعي إلى صفحة

تسجيل الدخول وعندما ألغي ال Role في هذا الــ Folder أستطيع الدخول إليه وتظهر رسالة الترحيب ، الأمر نفس الامر مع Folder الــ User

تأكدت من إرجاع القيمة في الكود التالي :

 return roles.ToArray();

عندما يتم تسجيل الدخول كـمدير يرجع قيمة Admin وفي حال كان مستخدم يرجع قيمة User

ويتم تسجيلها في الــ Global.asax

ولكن مع ذلك لا أستطيع الدخول إلى مجلد Admin أو USer في حال أستخدمت الــ Role

منذ كم يوم وأنا احاول واعدت كتابة المثال ولكن دونى فائدة ...

أرجو الإفادة وشكرا مقدما .

File.rar

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

عرفت سبب المشكلة.

مرة أخرى مشكور على الموضوع ,, عندي أستفسار بسيط أنا أستخدم طريقة FormsAuthenticationTicket

ومن ثم أقوم بعمل Encrypt للـــ Ticket أيهما أفضل الطريقة التي ذكرهتا أم الــ Ticket .

تم تعديل بواسطه vip_h
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم ورحمة الله وبركاته

أود أن أشكركم أخواني الكرام على مروركم

أما بالنسبة إلى

عرفت سبب المشكلة.

مرة أخرى مشكور على الموضوع ,, عندي أستفسار بسيط أنا أستخدم طريقة FormsAuthenticationTicket

ومن ثم أقوم بعمل Encrypt للـــ Ticket أيهما أفضل الطريقة التي ذكرهتا أم الــ Ticket .

بصراحة لا أعرف أي الطريقتين أفضل، ولكن ما أعرفه هو أنه لا توجد طريقة مطلقة، حيث أنه قد تكون هناك بيئة تفرض عليك إستخدام او تفضيل طريقة على أخرى. قد يجيب الرابط التالي على سؤالك أو على الأقل قد يضعك في الإتجاه المناسب

http://support.microsoft.com/kb/910443

أتمنى لكم التوفيق

2

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم أخ Robatic

شكرا الك على الشرح الرائع الله يجعله في ميزان حسناتك..

انا عملت موقع انترنت Web Application عملته عن طريق Microsoft Visual Studio 2008 بال Asp.net ولغة C#

وعملت ال login للمستخدم عن طريق ASP.NET Website Administration Tool (AWAT.. وانشألي قاعدة بيانات كامله باسم aspnetdb.mdf،

وعملت 2 Roles واحد للمستخدم والثاني لل admin

ولما اعمل تسجيل دخول بيدخل من غير مشاكل

السؤال كالتالي

كيف اعمل حتى كل مستخدم جديد تنشأ له صفحة خاصه فيه تمكنه من تغير الباسوورد او تعديل بياناته

كيف استخدم قاعدة البيانات aspnetdb.mdf في صفحتين المستخدم والadmin ? بمعنى :كيف اظهر البيانات المستخدمين اللي بيسجلو في صفحة ال admin حتى لما ادخل على اني ادمن ادخل للصفحة واشوف اللي جدول فيه هو نفس الجدول الموجود في aspnetdb.mdf بس انا بدي اضيفه في صفحة الadmin ?

هل ممكن اعمل جدول خاص Comment Box (يعني المستخدم اللي مسجل يضع تعليق على الموضوع) هل ممكن اعمل هذا الجدول داخل قاعدة البانات aspnetdb.mdf واستخدمة؟ وكيف ممكن اعملها عن طريق استخدام SqlDataSource و GridView بدون استخدام ال ajax ((لاني لما دورت عن طريق عملها لقيت بس كمان مع ال ajax هل فيه طريقة بدونه ))

هل ممكن اعمل جدول خاص ب Rate (يعني المستخدم اللي مسجل يضع تقييم لل الموضوع) هل ممكن اعمل هذا الجدول داخل قاعدة البانات aspnetdb.mdf واستخدمة؟ وكيف ممكن اعملها

وفي خاصية بدي اعملها للمستخدم وهي مثل (اضف الى عربة التسوق) انا عندي الموقع عبارة عن دروس وبدي اضيف تحت كل درس ايقونه عملها انها تضيف عنوان هذا الدرس كلنك إلى جدول خاص في صفحة المستخدم الخاصه هي add to favorites اضف الدرس كلنك فقط إلى جدول الfavorites (هي بس خاصية للتسهيل على المستخدم الوصول للدرس اللي حابب يقرأه بصفحته الخاصه )

هل ممكن اعملها؟ باستخدام نفس قاعدة البانات aspnetdb.mdf كيف ممكن اعملها

بالنسبة للموقع اخي انا وضعت مثال في هذا الرابط اتمنّى ان تطّلع عليه

http://www.mediafire.com/?qezj2qxzodq#1

بالنسبة للAdd to Favorite'Box انا اريد اضافة "عنوان الدرس فقط كرابط" في MyAccount المستخدم ...

انا عملت الجدول بالحقلين وهكذا ولكني ضعيفة في الداتا بيس ولست جيدة

كيف اعمل لوحة التحكّم للمستخدم ووضع ال Favorite Box فيه كالذي يشبه ال inbox الذي بالهوتميل - بالرسائل( بدالها يكون فقط لينكات اسماء الدروس .. ليس كالرسائل اللتي تفتح في نفس الصفحة) – والحذف فقط (حذف عنوان الدرس)

وماهو ايضا كود الحفظ العادي ؟؟؟

ملاحظة: انا استخدم برنامج Microsoft Visual Studio 2008 .Net framework 3.5 ENU

وللموقع ASP.NET ولغة ال C#

الخلاصة أخي آخر كل درس سيكون موجود كالتالي

Add comment للمستخدمين المسجلين فقط

رابط عندما يضغط عليه يظهر التكست بوكس "اللّي يكتب فيه

التعليق" وزر السبمت "اللّي يسجّل التعليق ويجعله يظهر للكل"

Add This Tutorial to your favoriteBox?

بحيث انه يضيف هذا الدرس الى صندوق المفضلة الموجود والخاص في حسابه

وانه يكون في My Account او Profile للمستخدم يظهر فيه هذا الصندوق

وتقيم الدرس ...

اعذرني اخي مرة اخرى من اخذ وقتك واشغالك او ازعاجك ولكني محتاجة لمساعده

شكرا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم ورحمة الله وبركاته

الأخت العزيزة Layla

بما إنك أستخدمتي AWAT فهذا سيجعلك مقيدة بالجداول التي تم إنشائها في aspnetdb.mdf هناك طريقين يحظراني لحل ما تواجهين

الأول : هو دراسة وتحليل الجداول المتعلقة بالمستخدمين الموجودة في aspnetdb.mdf (والتي فيها بعض البيانات مشفرة) ومن ثم ربط ما يهمك منهم بجدول الـ favorites مثلا.

الثاني : هو إستخدام الخاصية User.Identity.Name والتي سوف تقوم بإرجاع إسم المستخدم الحالي الذي قام بتسجيل الدخول ومن ثم إستخدامه في ربط المواضيع المفضله بالمستخدم، مثلا لو فرضنا أن جدول الـ favorites بالتركيب التالي

thread_id, user_name

ولكن المشكلة في الطريقة رقم 2 هي أنه جرت العادة بإستخدام Foreign Key لربط سجل بسجل آخر بحيث يمكنك الإستفادة من خاصية On Delete Cascade or Set to Null في حالة حذف السجل الذي يحوي الـ Primary Key

أتمنى للجميع التوفيق

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

شكرا على المجهود الكبير

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بارك الله فيك أخي الحبيب وجزاك الله خير فقد أفدتني كثيرا بهذا الدرس .

ورمضان مبارك علينا وعليكم جميعاً .

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

Robatic

يعطيك العافيه

سؤال بسيط : اي جزء من الشرح هو اللي يتحكم بمعلومات المستخدم ، اقصد لو المستخدم سجل الدخول وارسل فورم للداتابيز او سوى اي عمليه غيرت من المعلومات الخاصه فيه

ولو تنّقل المستخدم بين الروابط على سبيل المثال رابط 1, رابط 2 ... كيف ممكن نتاكد ان هذا المستخدم هو اللي سجل الدخول بالاول

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

بارك الله فيك .

تم تعديل بواسطه NOAR
0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

موضوع جدا جميل ومفيد

جزاك الله خير الجزاء

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

روعه والله روعه بارك الله فيك بارك الله فيك اخي الكريم

الف شكر لحضرتك

موضوع يستحق الوقوف عندة بقوة

تحياااتي

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

شكرا لم على الشرح الوافي وجعله الله في ميزان حسناتك

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم ورحمة الله,,,

كيف يتم اضافة الرول role للمستخدم عند التستجيل,, فرضا أنه بامكان المستخدم اختيار الرول على سبيل المتال لدينا مجموعة من الاقسام في الشركة وكل موضف تابع لقسم المحاسبة أو الموارد البشرية أو أو أو .... الخ؟؟ كيف يتم ذلك ؟ وشكرا

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم ورحمة الله,,,

كيف يتم اضافة الرول role للمستخدم عند التستجيل,, فرضا أنه بامكان المستخدم اختيار الرول على سبيل المتال لدينا مجموعة من الاقسام في الشركة وكل موضف تابع لقسم المحاسبة أو الموارد البشرية أو أو أو .... الخ؟؟ كيف يتم ذلك ؟ وشكرا

عندي مشكله اريد رفع aspnetdb.mdf على الدومين الذى فيه استضافة موقعى وفى قاعدة بيانات واحده فهل يمكن دمج الجدول فقط فى قاعدة البيانات و ثانيا ماذا افعل connection string شان يشوف قاعة البينات الخاصه بالعضويه

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

عندي مشكله اريد رفع aspnetdb.mdf على الدومين الذى فيه استضافة موقعى وفى قاعدة بيانات واحده فهل يمكن دمج الجدول فقط فى قاعدة البيانات و ثانيا ماذا افعل connection string شان يشوف قاعة البينات الخاصه بالعضويه

انظر الى المقالة التالية :

http://www.arabteam2000-forum.com/index.php?showtopic=129320

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

انظر الى المقالة التالية :

http://www.arabteam2000-forum.com/index.php?showtopic=129320

شكر الله لك و جعل ذلك فى ميزان حسناتك فقد فرجت عنا كربه

عندي سؤالين :-

- اذا اردت جمع memebership و قاعدة بياناتى هل تفضل ان ادمج العضويه فى القاعده بحيث انقل الجداول و البروسيديورز و لا اخليها attach file

- لو من خلال برنامجك اريد ان اجعل كود للمديرين يبدا admin ثم رقم المدير بحيث يدخل على صفحة التقارير فقط ماذا افعل

0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه
  • 0

السلام عليكم ورحمة الله وبركاته


 


موضوع رائع ومتميز..جزاكم الله خيراً وبارك الله فيكم


0

شارك هذا الرد


رابط المشاركة
شارك الرد من خلال المواقع ادناه

من فضلك سجل دخول لتتمكن من التعليق

ستتمكن من اضافه تعليقات بعد التسجيل



سجل دخولك الان

  • يستعرض القسم حالياً   0 members

    لا يوجد أعضاء مسجلين يشاهدون هذه الصفحة .