ASP.NET MVC条件路由
本文关键字:路由 条件 MVC NET ASP | 更新日期: 2023-09-27 18:00:25
在我的MVC应用程序中,我的路由定义如下:
routes.MapRoute(
"Category_default",
"{lang}/Category/{categoryid}/{controller}/{action}/{id}",
new { lang = "en", action = "Index", id = UrlParameter.Optional, categoryid = -1 }
).DataTokens.Add("area", "Category");
routes.MapRoute(
name: "Default",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { controller = "home", action = "index", lang = "en", id = UrlParameter.Optional }
);
该应用程序运行良好。然而,系统管理员刚刚告诉我,那些无法访问该类别的用户(换句话说,他们在逻辑上与该类别无关)也可以通过切换categoryid参数来查看数据,这并不奇怪,因为我没有在那里进行任何检查。
检查用户是否对此类别拥有权限的有效方法是什么。在系统中,我有一个User.AllowedCategories List的User对象,它包含用户可以访问的所有id的整数值。
类别区域有大约20个控制器(因此有20个视图)。我是否应该对每个视图进行逻辑检查?或者我可以用最少的编码/或者我可以把这个逻辑放在全局范围内吗?
您可以通过三种方式实现这一点,
方法1:全局过滤器
在FilterConfig.cs:中
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new ValidateUserFilter());
}
在ValidateUserFilter.cs 中
public class ValidateUserFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
//Controllers to avoid validation
if ((new[] { "<<CONTROLLER1>>", "<<CONTROLLER2>>" }).Any(x => x == filterContext.ActionDescriptor.ControllerDescriptor.ControllerName))
{
return;
}
if (!User.AllowedCategories.Any(x => x == FilterContext.RequestContext.RouteData.Values["id"]))
{
//Redirect user to unauthorized page.
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "Controller", "<<CONTROLLER_NAME>>" }, { "Action", "<<ACTION_NAME>>" } });
}
}
}
方法2:FilterAttribute
public class ValidateControllerAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (!User.AllowedCategories.Any(x => x == filterContext.RequestContext.RouteData.Values["id"]))
{
//Redirect user to unauthorized page.
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "Controller", "<<CONTROLLER_NAME>>" }, { "Action", "<<ACTION_NAME>>" } });
//OR, You can redirect to 403 response
//throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "You do not have permission to view this page");
}
}
}
您必须在每个想要的控制器中添加此属性验证
例如:
[ValidateController]
public class MyControllerController : Controller
方法3:ActionMethodSelectorAttribute
public class ValidateActionAttribute : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
if (!User.AllowedCategories.Any(x => x == controllerContext.RequestContext.RouteData.Values["id"]))
{
//Redirect user to unauthorized page.
controllerContext.HttpContext.Response.Clear();
controllerContext.HttpContext.Response.Redirect("~/<<CONTROLLER_NAME>>/<<ACTION_NAME>>");
return false;
//OR, You can redirect to 403 response
//throw new HttpException((int)System.Net.HttpStatusCode.Forbidden, "You do not have permission to view this page");
/*OR,
controllerContext.HttpContext.Response.StatusCode = 403;
return true;*/
}
}
}
你必须在你想要的每个动作中添加这个属性验证
例如:
[ValidateAction]
public ActionResult Index()
{
return View();
}
如果我做对了,本质上的问题是,未经授权的用户能够访问应用程序的某些部分,而这是不应该的。
您可以在操作方法上使用Authorize
属性,也可以在Controller类上使用,这取决于您希望获得授权的区域。如果您的设计允许,如果您不希望重复,也可以考虑创建一个base controller
并在其上应用Authorize属性。
现在使用Roles
或Users
参数指定这些控制器的有效用户
[Authorize(Roles = "Valid Roles", Users = "Valid Users")]
如果默认的Authorize属性不能满足您的需要,您可以始终创建自己的自定义属性进行授权。