فرض کنید در پروژهی جاری خودتون قصد دارید یک سیستم مدیریت سطوح دسترسی کاربران رو با انعطاف بالا پیاده سازی کنید . مثلا سیستم شما دارای صفحات مختلفی هستش که هر گروه کاربری اجازه دسترسی به هر صفحه رو نداره ... هدف اینه که شما این گروههای کاربری و سطوح دسترسی برای هر گروه رو برای سیستم مشخص کنید .
مثلا فقط کاربرانی که دسترسی admin دارن بتونن به صفحات مدیریتی دسترسی داشته باشن و ....
برای این منظور در دات نت کلاسی با نام Role Provider وجود داره که در ادامهی این مبحث به کار با اون میپردازیم.
مثلا فرض کنید قرار بر اینه که سطوح دسترسی رو از بانک اطلاعاتی استخراج کنیم . کلاس مذکور در فضای نام System.Web.Security قرار گرفته . برای شروع ما نیاز داریم یک نمونه از این کلاس رو پیاده سازی کرده و چند تابع از اون رو بازنویسی کنیم .
پیاده سازی کلاس به این صورته :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace Myproject.Security
{
public class CustomRoleProvider : RoleProvider
{
}
}
خب در مرحلهی بعد دو تابع از این کلاس رو بازنویسی میکنیم . اول تابع GetRolesForUser که در این مقاله وظیفهی استخراج لیست مجوزها برای هر کاربر رو از بانک اطلاعاتی داره که به شکل زیر پیاده سازی میشه .
public override string[] GetRolesForUser(string username)
{
using (DatabaseEntities db = new DatabaseEntities())
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase));
var roles = from ur in user.UserRoles
from r in db.Roles
where ur.RoleId == r.Id
select r.Name;
if (roles != null)
return roles.ToArray();
else
return new string[] {}; ;
}
}
همونطور که میبینید در تابع بالا از کلاس CustomRoleProvider ما عملیات استخراج لیست مجوزهای دسترسی مربوط به هر کاربر رو از بانک اطلاعاتی انجام دادیم . توجه داشته باشین که شما میتونید این واکشی رو از هر محیط دیگه ای جز بانک اطلاعاتی هم بسته به نوع کارتون انجام بدید .
تابع بعد IsUserInRole نام داره که با بازنویسی اون مشخص میکنیم که ایا یک کاربر دارای مجوز لازم برای دسترسی هست یا نه . اون رو به شکل زیر بازنویسی میکنیم.
public override bool IsUserInRole(string username, string roleName)
{
using (DatabaseEntities db = new DatabaseEntities())
{
User user = db.Users.FirstOrDefault(u => u.UserName.Equals(username, StringComparison.CurrentCultureIgnoreCase));
var roles = from ur in user.UserRoles
from r in db.Roles
where ur.RoleId == r.Id
select r.Name;
if (user != null)
return roles.Any(r => r.Equals(roleName, StringComparison.CurrentCultureIgnoreCase));
else
return false;
}
}
همونطور که شاهد هستید در تابع بالا بعد از واکشی لیست مجوزهای ثبت شده برای هر کاربر بررسی انجام میشه که ایا اولا کاربر یک کاربر ثبت شده هست و ثانیا اینکه ایا درخواستی که ارسال کرده برای دسترسی به یک بخش مجوز اون رو داره یا خیر ...
این نکته رو یاد آور بشم که این توابع رو میشه به شکلهای مختلفی پیاده سازی کرد و اونچه که در اینجا نوشته شده فقط جهت مثال هستش . مثلا تابع IsUserInRole رو میشه به شکل زیر هم نوشت و این بسته به شرایط کاری داره که قصد انجام اون رو دارید ....
public override bool IsUserInRole(string username, string roleName)
{
return this.GetRolesForUser(username).Contains(roleName);
}
خب میرسیم به بخش معرفی این Provider در web.config که به صورت زیر انجام میشه ...
<system.web>
...
<rolemanager cacherolesincookie="true" defaultprovider="CustomRoleProvider" enabled="true">
<providers>
<clear />
<add name="CustomRoleProvider" type="Myproject.Security.CustomRoleProvider" />
</providers>
</rolemanager>
...
</system.web>
توجه داشته باشید که مجوزهای هر کاربر با معرفی بالا بعد از یک بار واکشی در کوکی ذخیره میشه و دیگه هر بار، بار اضافه برای واکشی از بانک اطلاعاتی به برنامه تحمیل نمیشه ...
حالا به این صورت میتونیم مثلا یک Controller رو محافظت کنیم در برابر درخواست از جانب کاربرانی که سطح دسترسی به اون رو ندارند .
using System;
using System.Web.Mvc;
namespace MyProject.Areas.Admin.Controllers
{
[Authorize(Roles = "Administrators")]
public class HomeController : Controller
{
//
// GET: /Admin/Home/
public ActionResult Index()
{
return View();
}
}
}
توجه داشته باشید که کنترل مجوز برای بررسی وجود مجوز در بخشهای کوچکتر هم مانند اکشنها و ... میتونه در نظر گرفته بشه .