ASP.NET MVCページベースの権限管理
7792 ワード
ASP.NET MVCではAOPのアイデア(Filter)を用いてページレベルの権限を実現する.各ページでは、より小さなレベルの権限を管理します.
1.Models
1)PermissionItem
すべての権限リストを取得してキャッシュし、ユーザー権限を取得してキャッシュする2つの方法があります.
AuthorizeAttributeから継承し、そのOnAuthorizationメソッドを書き換え、AOPを実現します.
1)アクセス:http://localhost:5598/Home/Page1結果:
2)アクセス:http://localhost:5598/Home/Page2、結果:Page 2
3)アクセス:http://localhost:5598/Home/Page3、結果:Page 3
4)アクセス:http://localhost:5598/Home/Page4結果:
5)アクセス:http://localhost:5598/Home/Page5、結果:Page 5
6)アクセス:http://localhost:5598/Home/Page6結果:The page you want to access has not been configed permission.
具体的なロジックはコードを参照して推理してください.(UserID=1のユーザには2,3の権限があり,2,3の権限は2,3,5ページを見ることができるので,2,3,5へのアクセスのみが正当であり,その他はすべて不正であり,Page 6は構成されておらず,不正であり,返されるエラー情報が異なるだけである.
備考:このやり方は見たブログ園の中の仁兄のやり方から書いたもので、文章のリンクを忘れました.ここで感謝します.
1.Models
1)PermissionItem
namespace AspNetMvcAuthDemo1.Models
{
public class PermissionItem
{
public int ID { set; get; }
public int PermissionID { set; get; }
public string Name { set; get; }
public string Route { set; get; }
}
}
2)PermissionList namespace AspNetMvcAuthDemo1.Models
{
public class PermissionList
{
public int ID { set; get; }
public int PermissionID { set; get; }
public int UserID { set; get; }
}
}
3)UrlAuthorizeEntities namespace AspNetMvcAuthDemo1.Models
{
public class UrlAuthorizeEntities
{
public IEnumerable<PermissionItem> PermissionItems = new List<PermissionItem>
{
new PermissionItem{ ID = 1 , PermissionID = 1, Name = "Test Page 1", Route = "/Home/Page1" },
new PermissionItem{ ID = 2 , PermissionID = 2, Name = "Test Page 2", Route = "/Home/Page2" },
new PermissionItem{ ID = 3 , PermissionID = 3, Name = "Test Page 3", Route = "/Home/Page3" },
new PermissionItem{ ID = 4 , PermissionID = 1, Name = "Test Page 4", Route = "/Home/Page4" },
new PermissionItem{ ID = 5 , PermissionID = 2, Name = "Test Page 5", Route = "/Home/Page5" }
};
public IEnumerable<PermissionList> PermissionList = new List<PermissionList>
{
new PermissionList{ ID = 1 , PermissionID = 2, UserID = 1},
new PermissionList{ ID = 2 , PermissionID = 3, UserID = 1},
};
}
}
2.アカウントヘルプクラス-ACcountHelperすべての権限リストを取得してキャッシュし、ユーザー権限を取得してキャッシュする2つの方法があります.
namespace AspNetMvcAuthDemo1.UrlAuthorize
{
/// <summary>
/// Account Helper
/// </summary>
public static class AccountHelper
{
/// <summary>
/// Get all permission list
/// </summary>
/// <returns>Permission List</returns>
public static List<PermissionItem> GetPermissionItems()
{
if (HttpContext.Current.Cache["PermissionItems"] == null)
{
UrlAuthorizeEntities db = new UrlAuthorizeEntities();
var items = db.PermissionItems.Where(c => c.PermissionID > 0).ToList();
HttpContext.Current.Cache["PermissionItems"] = items;
}
return (List<PermissionItem>)HttpContext.Current.Cache["PermissionItems"];
}
/// <summary>
/// Get User Permission
/// </summary>
/// <param name="userID">User ID</param>
/// <returns>User Permission Array</returns>
public static Int32[] GetUserPermission(int userID)
{
if (HttpContext.Current.Session["Permission"] == null)
{
UrlAuthorizeEntities db = new UrlAuthorizeEntities();
var permissions = db.PermissionList.Where(c => c.UserID == userID).Select(c=>c.PermissionID).ToArray();
HttpContext.Current.Session["Permission"] = permissions;
}
return (Int32[])HttpContext.Current.Session["Permission"];
}
}
}
3.Filter(AOP)-UrlAuthorizeAttribute AuthorizeAttributeから継承し、そのOnAuthorizationメソッドを書き換え、AOPを実現します.
namespace AspNetMvcAuthDemo1.UrlAuthorize
{
/// <summary>
/// URL permission
/// </summary>
public class UrlAuthorizeAttribute : AuthorizeAttribute
{
/// <summary>
/// Rewrite OnAuthorization
/// </summary>
/// <param name="filterContext"></param>
public override void OnAuthorization(AuthorizationContext filterContext)
{
//Get permission list
List<PermissionItem> pItems = AccountHelper.GetPermissionItems();
//Get current page permission ID,if items is null,the page you what to access has not been configed.
var item = pItems.FirstOrDefault(c => c.Route == filterContext.HttpContext.Request.Path);
if (item != null)
{
int[] permissions = AccountHelper.GetUserPermission(int.Parse(filterContext.HttpContext.Session["UserID"].ToString()));
if (Array.IndexOf<Int32>(permissions, item.PermissionID) == -1)
{
//have not permission
filterContext.HttpContext.Response.Write("You have no permission to access this page.");
filterContext.HttpContext.Response.End();
}
}
else
{
//the page you what to access has not been configed.
filterContext.HttpContext.Response.Write("The page you want to access has not been configed permission.");
filterContext.HttpContext.Response.End();
}
}
}
}
4.せいぎょそうちnamespace AspNetMvcAuthDemo1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
public string Login()
{
HttpContext.Session["UserID"] = 1;
return "Login success.";
}
[UrlAuthorize]
public string Page1()
{
return "Page1";
}
[UrlAuthorize]
public string Page2()
{
return "Page2";
}
[UrlAuthorize]
public string Page3()
{
return "Page3";
}
[UrlAuthorize]
public string Page4()
{
return "Page4";
}
[UrlAuthorize]
public string Page5()
{
return "Page5";
}
[UrlAuthorize]
public string Page6()
{
return "Page6";
}
}
}
6.Route Config namespace AspNetMvcAuthDemo1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Login", id = UrlParameter.Optional }
);
}
}
}
効果:1)アクセス:http://localhost:5598/Home/Page1結果:
2)アクセス:http://localhost:5598/Home/Page2、結果:Page 2
3)アクセス:http://localhost:5598/Home/Page3、結果:Page 3
4)アクセス:http://localhost:5598/Home/Page4結果:
5)アクセス:http://localhost:5598/Home/Page5、結果:Page 5
6)アクセス:http://localhost:5598/Home/Page6結果:The page you want to access has not been configed permission.
具体的なロジックはコードを参照して推理してください.(UserID=1のユーザには2,3の権限があり,2,3の権限は2,3,5ページを見ることができるので,2,3,5へのアクセスのみが正当であり,その他はすべて不正であり,Page 6は構成されておらず,不正であり,返されるエラー情報が異なるだけである.
備考:このやり方は見たブログ園の中の仁兄のやり方から書いたもので、文章のリンクを忘れました.ここで感謝します.