ASP.NET MVC5中的自定义身份验证和授权?

时间:2016-10-13 04:07:59

标签: c# asp.net-mvc authentication asp.net-mvc-5 authorization

我有以下数据库结构 DB structure, authentication/authorization part 我必须为ASP.NET MVC 5站点构建身份验证/授权。

数据库架构的工作方式如下:每个user属于group,每个group可以被授予/拒绝permission。每个权限都与控制器上的操作相匹配(例如,Petitions控制器将执行以下操作:ListViewAdd,{{1 },EditDeleteVoteForVoteAgainstReject,每个操作都是Approve表中的一个条目。 / p>

所有这一切的目的是,每次用户调用某个操作时,该站点都会验证该用户是否属于已被授予该操作权限的组,并做出相应的反应。

示例:我们假设管理员授予PermissionsPetitionsListPetitionsViewPetitionsApprovePetitionsReject权限,以及ManagersPetitionsListPetitionsViewPetitionsAddPetitionsVoteForPetitionsVoteAgainst群组。

在这种情况下,两个小组都可以

  • 列出请愿书
  • 查看请愿书

经理可以

  • 批准请愿书
  • 拒绝请愿

但他们无法

  • 投票请愿
  • 投票反对请愿书。

以同样的方式,用户可以

  • 添加请愿书
  • 投票请愿
  • 投票反对请愿

但他们不能:

  • 批准请愿书
  • 拒绝请愿

并且都不能编辑或删除请愿书。

我真的很想利用MVC 5中的属性功能。我的想法是构建自定义属性,在幕后执行所有身份验证/授权。像这样:

Users

请注意每个操作的public class PetitionsController : Controller { [MyCustomAuth(Permission="PetitionsList",Groups="Users,Managers")] public ActionResult List() { //show the list of petitions } [MyCustomAuth(Permission="PetitionsView",Groups="Users,Managers")] public ActionResult View() { //show a specific petition } [MyCustomAuth(Permission="PetitionsAdd",Groups="Users")] public ActionResult Add() { //show add petition form } [HttpPost] [MyCustomAuth(Permission="PetitionsAdd",Groups="Users")] public ActionResult Add(object[] params) { //save new petition } [MyCustomAuth(Permission="PetitionsEdit",Groups="Admins")] public ActionResult Edit(int id) { //show edit petition form } [HttpPost] [MyCustomAuth(Permission="PetitionsEdit",Groups="Admins")] public ActionResult Edit(object[] params) { //save changes to petition } [HttpPost] [MyCustomAuth(Permission="PetitionsDelete",Groups="Admins")] public ActionResult Delete(int_id) { //delete petition } [HttpPost] [MyCustomAuth(Permission="PetitionsVoteFor",Groups="Users")] public ActionResult VoteFor(int id) { //add vote supporting petition } [HttpPost] [MyCustomAuth(Permission="PetitionsVoteAgainst",Groups="Users")] public ActionResult VoteAgainst(int id) { //add vote against petition } [HttpPost] [MyCustomAuth(Permission="PetitionsApprove",Groups="Managers")] public ActionResult Approve(int id) { //approve petition } [HttpPost] [MyCustomAuth(Permission="PetitionsReject",Groups="Managers")] public ActionResult Reject(int id) { //reject petition } } 属性。如果用户实际上有权在幕后执行该操作,那么我希望该属性能够做大量工作。当然,如果它未经过身份验证/授权,该属性应该重定向到登录页面/ 401 /其他地方。

我的问题是,我从哪里开始?我是否希望从MVC 5中的某些类实现一些特殊的接口/继承?或者我是否必须从头开始写这个?

另外,请提前感谢阅读这一文本墙并向我提供正确方向的提示/指示。

1 个答案:

答案 0 :(得分:1)

我认为你可以从下面的自定义授权过滤器开始。它还处理两者的情况 - ajax请求和整页请求。

 public class MyCustomAuthAttribute : FilterAttribute, IAuthorizationFilter
    {
        public string Permission { get; set; }
        public string Groups { get; set; }

        public void OnAuthorization(AuthorizationContext filterContext)
        {
            bool isauthorized = CheckIfUserIsAuthorized();
            if (!isauthorized)
                context.Result = new HttpUnauthorizedResult(); // mark unauthorized

            // Only do something if we are about to give a HttpUnauthorizedResult and we are in AJAX mode.
            if (filterContext.Result is HttpUnauthorizedResult && filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult
                {
                    Data = new { Success = false, Message = "Unauthorized Access" },
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet
                };
            }
            else
            {
                base.OnAuthorization(filterContext);
                if (filterContext.Result is HttpUnauthorizedResult)
                {
                    HttpContext.Current.Session.Abandon();
                    System.Web.Security.FormsAuthentication.SignOut();
                    filterContext.Result = new RedirectResult("Your Login Page.");
                }
            }
        }

        private bool IsAuthorizedUser()
        {
            // use Permission, Groups and your logic
        }
    }

并按照您提到的方式使用它:

 [MyCustomAuth(Permission="PetitionsEdit",Groups="Admins")]