PDA

View Full Version : Authentication & Roles



mehdi58
شنبه 20 بهمن 1386, 22:13 عصر
با سلام
اول از همه به خاطر طولانی بودن تاپیک از همه دوستان معذرت خواهی می کنم . ( جهت اطلاع دوستان بگم که من از ASP.NET 1.x استفاده می کنم )
فرض کنید که سه تا دایرکتوری مختلف دارم با سه تا نقش مجزا و می خوایم که هر کاربر با توجه به نقشش فقط بتونه صفحات مربوط به خودش رو ببینه.
کاربران من بعضی هاشون فقط یه نقش و بعضی هاشون بیش از یه نقش دارن . از طرفی ( با توجه به نظر کارفرما ) هر کاربر فقط یه دونه کلمه کاربری ( Username ) داره ( یعنی اگه دوتا نقش هم داشته باشه باز هم یه Username داره ) .
روال کار به این صورته که ابتدا کاربر وارد صفحه Login می شه ، و User و Pass اش چک می شه و در صورتیکه در دیتا بیس موجود بود ، یه لیست از نقشهای مجازش رو می بینه .
حالا بعد از انتخاب یکی از اون نقشها ، کدهای زیر رو داریم :



Dim strVal As Integer= RadioButtonList1.SelectedValue

'تعیین حق دسترسی کاربر
Select Case strVal
‘ورود نقش 1
Case 1
Call userName_session()
Call roleset("role1")
Response.Redirect("role1/ role1HOME.aspx")

‘ورود نقش 2
Case 2
Call userName_session()
Call roleset("role2")
Response.Redirect("role2/role2HOME.aspx")

‘ورود نقش 3
Case 3
Call userName_session()
Call roleset("role3")
Response.Redirect("role3/role3HOME.aspx")

End Select

--------------------------------------------------------------------

Public Sub userName_session()
Session("userName") = TextBox1.Text
Session("role") = RadioButtonList1.SelectedItem.Text
End Sub

--------------------------------------------------------------------

Public Sub roleset(ByVal r As String)
FormsAuthentication.Initialize()
Dim ticket As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, Session("userName"), DateTime.Now, DateTime.Now.AddMinutes(15), True,FormsAuthentication.FormsCookiePath)
Dim hash As String = FormsAuthentication.Encrypt(ticket)
Dim cookie As HttpCookie = New HttpCookie(FormsAuthentication.FormsCookieName, hash)
If ticket.IsPersistent Then
cookie.Expires = ticket.Expiration
End If

Response.Cookies.Add(cookie)
End Sub

--------------------------------------------------------------------

و با این کار به صفحه مربوط به نقشش هدایت می شه.

فایلهای Web.Config مربوط به هر کدوم از دایرکتوریهام به صورت زیره :



<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<authorization>
<allow roles="role1"/>
role2 و role3 برای سایر دایرکتوریها نبز به همین ترتیب
<deny users="*" />
</authorization>
</system.web>
</configuration>

و فایل Web.Config پروژه هم به صورت زیره :



<?xml version="1.0" encoding="utf-8"?>
<configuration>

<system.web>
<compilation defaultLanguage="vb" debug="true">
<assemblies>
<add assembly="CrystalDecisions.CrystalReports.Engine, Version=9.1.5000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
<add assembly="CrystalDecisions.ReportSource, Version=9.1.5000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
<add assembly="CrystalDecisions.Shared, Version=9.1.5000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
<add assembly="CrystalDecisions.Web, Version=9.1.5000.0, Culture=neutral, PublicKeyToken=692fbea5521e1304"/>
</assemblies>
</compilation>

<!--********************** Page Error **********************-->
<customErrors defaultRedirect="PageError.aspx" mode="RemoteOnly"/>

<authentication mode="Forms">
<forms name="myCookie" loginUrl="index.aspx" protection="All" timeout=10 path="/">
<credentials passwordFormat="SHA1">
</credentials>
</forms>
</authentication>






<authorization>
<allow users="*"/>
</authorization>

<trace enabled="false" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true"/>

<sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" cookieless="false" timeout="15"/>

<globalization requestEncoding="utf-8" responseEncoding="utf-8"/>

</system.web>


<location path="Pageerror.aspx">
<system.web>
<authorization>
<allow roles="db"/>
<deny users="*"/>
</authorization>
</system.web>
</location>


<location path="errorMessage.aspx">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>


</configuration>

حالا اگه یه کاربر بخواد بدون لوگین کردن وارد یه صفحه بشه بهش اجازه داده نمی شه و همین طور اگه کاربری بعد از لوگین توی Url آدرسی رو تایپ کنه که مربوط به نقشش نیست باز هم وارد اون صفحه نمی تونه بشه .

فرض می کنیم کاربر X با نقش role1 لوگین می کنه و به آدرس http:\\ localhost\myproj\role1\role1home.aspx منتقل می شه .
( از این به بعد در هر کدوم از صفحات Username‌ اش نمایش داده می شه )
اما مشکل اینه که مثلا اگه این کاربر در حین انجام کار یه پنجره دیگه IE رو باز کنه و یه آدرسی مثل http:\\ localhost\myproj\role1\role1page.aspx رو تایپ کنه اون وقت بعضی وقتها با صفحه خطا روبرو می شه و بعضی وقتها هم صفحه مورد نظر درست لود می شه اما در جلوی نام کاربر چیزی نمایش داده نمی شه .
به نظر شما دلیلش چی می تونه باشه ؟

mehdi58
دوشنبه 22 بهمن 1386, 13:12 عصر
به نظر دوستان آیا اصلا روش من درسته ؟
اگه غلطه ، می شه روش صحیح واسه این کار رو ارائه کنین ؟
متشکرم

Alireza_Salehi
دوشنبه 22 بهمن 1386, 13:56 عصر
اولا نباید کاربر خودش نقشش رو انتخاب کنه باید به صورت اتوماتیک وقتی لاگین کرد نقشش تشخیص داده بشه و به صفحه مربوطه هدایت بشه.

بعدش هم ما که علم غیب نداریم، پیام خطا چی بوده!

mehdi58
دوشنبه 22 بهمن 1386, 22:33 عصر
اولا نباید کاربر خودش نقشش رو انتخاب کنه باید به صورت اتوماتیک وقتی لاگین کرد نقشش تشخیص داده بشه و به صفحه مربوطه هدایت بشه.

دوست عزیز شما گویا تاپیک رو بطور دقیق مطالعه نکردین .
من گفتم که یه کاربر امکان داره چند تا نقش داشته باشه مثلا علاوه بر اینکه مدیر یه بخشه ، می تونه یه کارمند هم باشه و چون این کاربر فقط یه کلمه عبور داره پس هنگام لوگین چیزی رو نمی شه تشخیص داد ، پس قاعدتا می بایست نقشهای ست شده رو بهش نشون داد تا با انتخاب یکی از اونها بتونه به صفحات مجاز دسترسی داشته باشه .

Behrouz_Rad
دوشنبه 22 بهمن 1386, 23:35 عصر
مطمئنی این کدها کار می کنند؟!
نقش کاربر رو که در کوکی ذخیره نکردی!
روال Application_AuthenticateRequest کجاست؟
اصلا کوکی تصدیق هویت رو به سیستم کاربر منتقل نکردی! Redirect کجاست؟


من گفتم که یه کاربر امکان داره چند تا نقش داشته باشه مثلا علاوه بر اینکه مدیر یه بخشه ، می تونه یه کارمند هم باشه و چون این کاربر فقط یه کلمه عبور داره پس هنگام لوگین چیزی رو نمی شه تشخیص داد ، پس قاعدتا می بایست نقشهای ست شده رو بهش نشون داد تا با انتخاب یکی از اونها بتونه به صفحات مجاز دسترسی داشته باشه .

نقش(های) کاربر، وظایف و حوزه ی عملکرد هر نقش در دیتابیس ذخیره میشه.
مگر در این سایت موقع لوگین نوع نقش باید تعیین بشه؟ (من هم مدیرم هم کاربرم)!
ساختار دیتابیست رو باید اصلاح کنی.

موفق باشید.

Alireza_Salehi
سه شنبه 23 بهمن 1386, 09:24 صبح
دوست عزیز شما گویا تاپیک رو بطور دقیق مطالعه نکردین .
من گفتم که یه کاربر امکان داره چند تا نقش داشته باشه مثلا علاوه بر اینکه مدیر یه بخشه ، می تونه یه کارمند هم باشه و چون این کاربر فقط یه کلمه عبور داره پس هنگام لوگین چیزی رو نمی شه تشخیص داد ، پس قاعدتا می بایست نقشهای ست شده رو بهش نشون داد تا با انتخاب یکی از اونها بتونه به صفحات مجاز دسترسی داشته باشه .

این مسئله تناقضی با مطلبی که من گفتم نداره ، فیلتر کردن قابلیت ها و حقوق یک کاربر حتی اگر 100 تا نقش هم داشته باشه نیازی به انتخاب نقش توسط کاربر نداره!

در ساده ترین حدش ASP.NET این کار رو برای شما به صورت اتوماتیک انجام میده! هر چند سفارشی کردنش هم کاری نداره.

mehdi58
چهارشنبه 24 بهمن 1386, 09:52 صبح
خوب من یه سوال دارم .
اگه یه کاربر دارای نقش مدیریت پروژه باشه و یه نقش دیگه مثل مدیریت یه بخش ( از لحاظ چارت سازمانی) و این دو نقش از لحاظ عملکرد توی سایت هیچ اشتراکی هم با هم نداشته باشند به نظر شما وقتی کاربر Login کرد اون وقت از کجا می شه تشخیص داد که می خواد با عنوان مدیر پروژه وارد سیستم بشه یا با عنوان مدیر بخش .

hamedgh
چهارشنبه 24 بهمن 1386, 10:20 صبح
این جور که صحبت می کنی انگار مشکلاتت بیخ دار تر از این حرفهاست
اگر خودت می خواهی کنترل کنی که باید در page_load تک تک کنترل کنی اگر مربوط به این
نقش بود نیاید اینجا یا اگر بود مثلا برود کجا.......
ولی اگر از خود membeship استفاده می کنی به نظر من برای هر نقش یک پوشه در نظر بگیر
و صفحاتش را در ان بریز و با ان کد deny کن هر کسی که نمی خواهی بیاید داخل!
و اگر هم خواستی تک تک صفحات به طور مجزا معلوم کنی باز با کد location در وب کانفیگ
می توانی ان را هدایت کنی ......... یه اینجا هم سری بزن !
http://asp.net/learn/security/

Alireza_Salehi
چهارشنبه 24 بهمن 1386, 11:07 صبح
خوب من یه سوال دارم .
اگه یه کاربر دارای نقش مدیریت پروژه باشه و یه نقش دیگه مثل مدیریت یه بخش ( از لحاظ چارت سازمانی) و این دو نقش از لحاظ عملکرد توی سایت هیچ اشتراکی هم با هم نداشته باشند به نظر شما وقتی کاربر Login کرد اون وقت از کجا می شه تشخیص داد که می خواد با عنوان مدیر پروژه وارد سیستم بشه یا با عنوان مدیر بخش .

در بحث امنیتش همون پوشه پوشه کردن نقش ها و تنظیم سطح دسترسی در فایل های Web.Config یا استفاده از تگ Location در Web.Config اصلی کار رو راه میندازه.

در قسمت نمایش و این که وقتی کاربر چند تا نقش داره هم با توجه به نقش هایی که داره منوها و لینک هایی رو که نباید ببینه فیلتر می کنند!
اونهایی رو هم که باید ببینه میشه دسته بندی کرد و گفت مربوط به کدوم نقشش میشه!

این فیلتر کردن با استفاده از کنترل LoginView یا SecurityTrimming در SiteMap قابل انجامه ، اگر امکانات بیشتری می خواهید خودتون یه سفارشی شدش رو بسازید.

اصلا یک سوال اگر من به عنوان یک کارمند 3 تا نقش در سازمان داشته باشم مگر مهمه با کدوم وارد شدم ، همه اون کارهایی که در نقش های من وجود داره باید بتونم انجام بدم!
مگر این که منطق دیگری برای سازمان در نظر گرفته شده باشه!
مثلا اگر به عنوان مدیر پروژه وارد شدن نتونم مدیریت بخش رو انجام بدم! :متفکر:

Mahdi.Kiani
چهارشنبه 24 بهمن 1386, 15:51 عصر
من فکر می کنم که این دوستمون یه مقداری در بحث سطوح دسترسی ها دچار ابهام شدند و معنی اون ها را درست متوجه نشدند.
تا اونجایی که من می دونم تعیین سطوح بین کاربران برنامه معمولا به روش های زیر انجام میشه
1) یا برای هر قسمت از برنامه ، یک گزینه مشخص میشه که کاربر خاصی یا می تونه به اون گزینه دسترسی داشته باشه یا اینکه نمی تونه
مثلا اگر همین فروم ها Vbulletin را دیده باشین، و در واقع ادمین اون بوده باشین، موقعی که می خواین یه کاربری را به عنوان مدیر انتخاب کنید، n تا گزینه به صورت yes یا no هست که می تونین اون را برای اون مدیر تنظیم کنید. در این حالت مثلا یک مدیر بخش ممکنه به پروفایل شما دسترسی داشته باشه و یک مدیر خش دیگه به اون دسترسی نداشته باشه. (دقت کنید که هر دو به عنوان مدیر بخش اعلام شدند)
2) یه راه دیگه ام که من دیدم اینه که در برنامه اجازه تعریف role ها به ادمین سایت داده میشه، مثلا تعریف role مدیر بخش با تعیین یک سری خصوصیات و دسترسی های مشخص شده.. در این حالت دو مدیر بخش دقیقا دارای یک نوع دسترسی خواهند بود
3) وحالت سوم هم که دیدم خیلی ها از اون استفاده می کنند ، ترکیبی از دو روش فوق هست.

اما در همه این ها ، هیچ وقت معنی نمیده که یک نفر هم مدیر بخش باشه و هم مدیر ارشد. در واقع اینطوری گفته میشه که هر مدیر ارشد، یک مدیر بخش هم هست. چون مدیر ارشد، علاوه بر دسترسی های مدیر بخش، یک سری دسترسی های دیگه ای هم داره که مدیر بخش ممکنه نداشته باشه.مثلا ban کردن کاربران یا هر چیزی که توسط ادمین سایت مشخص شده باشه..

پس به نظر من اصلا معنی نمیده که بخوایم این طوری در نظر بگیریم که مثلا آقای behruz_rad هم به عنوان مدیر ناظر وارد بشه و هم به عنوان مدیر بخش.
اگر سطح دسترسی ایشون مثلا مدیر ناظر باشه، خوب طبیعتا مدیر تمامی بخش ها هم ممکنه باشه و اگر هم مدیر بخش باشه که خوب فقط کارای مدیر بخش را می تونه انجام بده

در کل اینکه هر نفر میتونه یه سطح دسترسی داشته باشه، از ادمین سایت گرفته تا کاربر معمولی سایت. پس وقتی یه نفر به عنوان مدیر کل سایت وارد میشه، هم مدیر کل سایت هست. هم مدیر ارشد. هم مدیر ناظر و هم مدیر بخش و هم یک کاربر معمولی..
اما یک کاربر معمولی فقط یک کاربر معمولی است با سطح دسترسی مشخص .. مثلا پاک کردن تاپیک خودش یا .....
امید وارم تونسته باشم خوب توضیح داده باشم
اگر هم جاییش اشتباه بود، دوستان محبت کنن و ما رو هم بیشتر روشنا کنند
یا علی

mehdi58
چهارشنبه 24 بهمن 1386, 22:54 عصر
مطمئنی این کدها کار می کنند؟!
نقش کاربر رو که در کوکی ذخیره نکردی!
روال Application_AuthenticateRequest کجاست؟
اصلا کوکی تصدیق هویت رو به سیستم کاربر منتقل نکردی! Redirect کجاست؟
موفق باشید.


ببخشین فراموش کردم اونها رو اینجا بگذارم :
Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
' Fires upon attempting to authenticate the use
If Request.IsAuthenticated Then
If HttpContext.Current.User.Identity.Name <> "" Then
Dim id As FormsIdentity = HttpContext.Current.User.Identity
Dim ticket As FormsAuthenticationTicket = id.Ticket

Dim userdata As String = ticket.UserData
Dim roles() As String = userdata.Split(",")
Dim spf As String
For i As Integer = 0 To roles.Length - 1
spf = roles(i).ToString
Next
HttpContext.Current.User = New System.Security.Principal.GenericPrincipal(id, roles)
End If
End If
End Sub


آقا بهروز فکر می کنم درست کار بکنه چون هیچ کاربری بدون Login اجازه ورود رو پیدا نمی کنه و نمی تونه با تایپ آدرس توی URL به صفحه مجازش قبل از Login دسترسی پیدا کنه .

حالا با این همه به نظر شما کدها ایراد دارن ؟
بهروز جان ای کاش مثل همیشه یه مقاله توپ در این زمینه می نوشتی !
باور کن وقتی توی فروم در این زمینه Search می کنم بد جوری سر در گم می شم چون واقعا نمی شه ایده های مختلف توی تاپیکها رو یه جا دسته بندی کرد و به یه نتیجه کلی رسید .
موفق باشی

mehdi58
چهارشنبه 24 بهمن 1386, 23:00 عصر
این جور که صحبت می کنی انگار مشکلاتت بیخ دار تر از این حرفهاست
اگر خودت می خواهی کنترل کنی که باید در page_load تک تک کنترل کنی اگر مربوط به این
نقش بود نیاید اینجا یا اگر بود مثلا برود کجا.......
ولی اگر از خود membeship استفاده می کنی به نظر من برای هر نقش یک پوشه در نظر بگیر
و صفحاتش را در ان بریز و با ان کد deny کن هر کسی که نمی خواهی بیاید داخل!
و اگر هم خواستی تک تک صفحات به طور مجزا معلوم کنی باز با کد location در وب کانفیگ
می توانی ان را هدایت کنی ......... یه اینجا هم سری بزن !
http://asp.net/learn/security/

دوست خوبمون arsp جواب شما رو دادن و اینکه دوست عزیز در ASP.NET 1.X چیزی به اسم membership نداریم !!!

mehdi58
چهارشنبه 24 بهمن 1386, 23:07 عصر
آقا ما ایرونی ها یه عادت بد داریم و اون هم اینه که اگه به ما بگن اگه از این طرف بری می افتی تو چاه ، عهد از همون طرف می ریم ، یا مثلا به یه چیزی گیر می دیم که نبایست گیر بدیم ( البته با عرض معذرت از همه دوستان خوبی که توی این تاپیک اظهار نظر می کنن )
دوستان عزیز بی خیال این موضوع نقش کاربر بشین چون این پروژه با اون چیزی که توی ذهن شماست زمین تا آسمون فرق می کنه و بنده ناگزیرم تمامی فرمایشات کارفرما رو مو به مو اجرا کنم و تمامی مطالبی هم که شما در مورد نقشها می گین رو قبول دارم و می دونم و ...
پس امیدوارم به اصل موضوع بپردازین .
با تشکر از همه

Behrouz_Rad
پنج شنبه 25 بهمن 1386, 00:11 صبح
ببخشین فراموش کردم اونها رو اینجا بگذارم :
Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)
' Fires upon attempting to authenticate the use
If Request.IsAuthenticated Then
If HttpContext.Current.User.Identity.Name <> "" Then
Dim id As FormsIdentity = HttpContext.Current.User.Identity
Dim ticket As FormsAuthenticationTicket = id.Ticket

Dim userdata As String = ticket.UserData
Dim roles() As String = userdata.Split(",")
Dim spf As String
For i As Integer = 0 To roles.Length - 1
spf = roles(i).ToString
Next
HttpContext.Current.User = New System.Security.Principal.GenericPrincipal(id, roles)
End If
End If
End Sub


آقا بهروز فکر می کنم درست کار بکنه چون هیچ کاربری بدون Login اجازه ورود رو پیدا نمی کنه و نمی تونه با تایپ آدرس توی URL به صفحه مجازش قبل از Login دسترسی پیدا کنه .

حالا با این همه به نظر شما کدها ایراد دارن ؟
بهروز جان ای کاش مثل همیشه یه مقاله توپ در این زمینه می نوشتی !
باور کن وقتی توی فروم در این زمینه Search می کنم بد جوری سر در گم می شم چون واقعا نمی شه ایده های مختلف توی تاپیکها رو یه جا دسته بندی کرد و به یه نتیجه کلی رسید .
موفق باشی
توی این خط:


Dim ticket As FormsAuthenticationTicket = New FormsAuthenticationTicket(1, Session("userName"), DateTime.Now, DateTime.Now.AddMinutes(15), True,FormsAuthentication.FormsCookiePath)

تو از Overload ای استفاده کردی که پارامتر UserData نداره! در نتیجه Role ای برای GenericPrincipal تعریف نشده!
کدهات چند تا مشکل داره که با مطالعه ی اون مقاله ی معروفی که در سایت CodeProject هست مشکلت برطرف میشه.
واسه هر چیزی که من نباید مقاله بنویسم :چشمک:

موفق باشید.