Nói cách khác, đây có phải là một ý tưởng thực sự ngu ngốc?Làm cách nào để tạo một AuthorizeAttribute tùy chỉnh dành riêng cho khu vực, bộ điều khiển và hành động?
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthorizeActionAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
// get the area, controller and action
var area = filterContext.RouteData.Values["area"];
var controller = filterContext.RouteData.Values["controller"];
var action = filterContext.RouteData.Values["action"];
string verb = filterContext.HttpContext.Request.HttpMethod;
// these values combined are our roleName
string roleName = String.Format("{0}/{1}/{2}/{3}", area, controller, action, verb);
// set role name to area/controller/action name
this.Roles = roleName;
base.OnAuthorization(filterContext);
}
}
CẬP NHẬT Tôi đang cố gắng để tránh những điều sau đây, trong một kịch bản mà chúng tôi có quyền vai trò cực kỳ hạt vì những vai trò được thiết lập trên một cơ sở cho mỗi khách hàng và gắn liền với nhóm người dùng:
public partial class HomeController : Controller
{
[Authorize(Roles = "/supplierarea/homecontroller/indexaction/")]
public virtual ActionResult Index()
{
return View();
}
[Authorize(Roles = "/supplierarea/homecontroller/aboutaction/")]
public virtual ActionResult About()
{
return View();
}
}
Bất cứ ai có thể khai sáng cho tôi một cách an toàn để viết AuthorizeRouteAttribute này để truy cập thông tin tuyến đường và sử dụng tên này làm tên vai trò? Như Levi nói, RouteData.Values không an toàn.
Việc sử dụng tệp httpContext.Request.Path có thực thi an toàn hơn hay tốt hơn không?
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
// auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
return;
}
var path = filterContext.HttpContext.Request.Path;
var verb = filterContext.HttpContext.Request.HttpMethod;
// these values combined are our roleName
string roleName = String.Format("{0}/{1}", path, verb);
if (!filterContext.HttpContext.User.IsInRole(roleName))
{
// role auth failed, redirect to login page
filterContext.Result = new HttpUnauthorizedResult();
// P.S. I want to tell the logged in user they don't
// have access, not ask them to login. They are already
// logged in!
return;
}
//
base.OnAuthorization(filterContext);
}
này có thể minh họa cho vấn đề xa hơn một chút:
enum Version
{
PathBasedRole,
InsecureButWorks,
SecureButMissingAreaName
}
string GetRoleName(AuthorizationContext filterContext, Version version)
{
//
var path = filterContext.HttpContext.Request.Path;
var verb = filterContext.HttpContext.Request.HttpMethod;
// recommended way to access controller and action names
var controller =
filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var action =
filterContext.ActionDescriptor.ActionName;
var area = "oh dear...."; // mmmm, where's thearea name???
//
var insecureArea = filterContext.RouteData.Values["area"];
var insecureController = filterContext.RouteData.Values["controller"];
var insecureAction = filterContext.RouteData.Values["action"];
string pathRoleName =
String.Format("{0}/{1}", path, verb);
string insecureRoleName =
String.Format("{0}/{1}/{2}/{3}",
insecureArea,
insecureController,
insecureAction,
verb);
string secureRoleName =
String.Format("{0}/{1}/{2}/{3}",
area,
controller,
action,
verb);
string roleName = String.Empty;
switch (version)
{
case Version.InsecureButWorks:
roleName = insecureRoleName;
break;
case Version.PathBasedRole:
roleName = pathRoleName;
break;
case Version.SecureButMissingAreaName:
// let's hope they don't choose this, because
// I have no idea what the area name is
roleName = secureRoleName;
break;
default:
roleName = String.Empty;
break;
}
return roleName;
}
Bạn có thể thêm câu trả lời của mình để hiển thị cách đề xuất hoạt động trong mã không? Chúng tôi đang sử dụng các khu vực, vì vậy nó sẽ cần phải phản ánh điều này cũng như các bộ điều khiển và hành động. Không quan tâm, bạn có thể thực sự phù hợp với bộ điều khiển hoặc hành động (ví dụ như được đề xuất:/myarea/mycontroller/myaction '; DROP TABLE thành viên; - /)? Chắc chắn MVC sẽ không phù hợp với bộ điều khiển hay hành động ngay từ đầu? – Junto
Đã cập nhật câu trả lời để giải quyết câu hỏi của bạn. – Levi
Hi Levi, tôi hiểu rằng tôi có thể sử dụng (string controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName; string action = filterContext.ActionDescriptor.ActionName;) nhưng tôi không thể truy cập vào tên khu vực theo cùng một cách. Tuy nhiên, không có AreaName có sẵn. Tôi có thể xác định vị trí đó ở đâu? Một ví dụ mã đơn giản sẽ đóng câu hỏi này. – Junto