【发布时间】:2011-09-22 17:57:14
【问题描述】:
我想简单地从控制器检查另一个 URL 是否被授权。
例如,我想像这样调用控制器:
[HttpPost]
public ActionResult IsUrlAuthorized(string url)
{
bool isAuthorized = // What do I put here?
return Json(isAuthorized);
}
所以我想知道我可以调用什么来检查当前用户是否有权使用传入的 URL。我猜答案与 Routes 有关,它位于 MVC 之外?
这是一个有点相似的问题,但并不完全相同: ASP.NET MVC. Check if user is authorized from JavaScript
因为用户通常可能会或可能不会被授权,但可能没有正确的权限或角色分配来查看特定的 URL。
想法?
更新:我使用标准的 MVC 授权属性来锁定我的应用程序,所以我将在这里给出一个示例。在 MVC 路由映射到控制器。 Controller 上的单个方法可以限制为一个或多个角色:
public class HomeController : Controller
{
[Authorize(Roles = "User, Moderator")]
public ActionResult ListRecentPosts()
{
. . .
}
}
或者,可以将整个 Controller 限制为一个或多个角色:
[Authorize(Roles = "Admin")]
public class AdminController : Controller
. . .
这些控制器方法响应的实际 URL 是基于标准 MVC 应用程序中的默认映射:
routes.MapRoute("Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
但是,您可以对您的用户友善,并通过添加更多路由来使 URL 可猜测 - 因此,控制器方法可以有许多指向它的名称。您不能只从 URL 中假设和推断控制器名称(即使它映射到站点中一半的 URL)。
所以大概我需要一种方法来直接询问路由引擎是否为当前用户授权 URL,或者需要两步询问路由引擎哪个控制器和方法,然后询问这些是否被授权 - 希望不要直接使用反射和匹配角色,因为这似乎又假设太多了。
更新 2:出现这种情况的方式是我的应用顶部有一个帐户条。通过选择您被授权的多个帐户之一,可以更改其状态。根据您在应用程序中的位置,您选择的帐户可能有权查看此页面 - 您可能正在填写您不想丢失的表格。所以这种幼稚的方法——当他们选择另一个帐户时才刷新——是有害的,并且即使没有表单并且他们只是在阅读一个全是文本的页面,也会浪费用户的时间。
虽然为用户带来了便利,但用户会公平地假设他们无法看到的页面确实被拒绝(并且,将它们留在被禁止的页面 - 从中采取的操作将失败)。所以我需要知道是否根据他们的新权限重定向。
我喜欢 .Net 的一个原因是它的许多最佳库的分解方式非常好,因此您可以轻松地重新组合属于其正常功能的一部分或新的变化。路由模块和 MVC 似乎都构造得很好,所以我不得不怀疑这是可以做到的。
廉价的技巧是确保我的授权模块在用户未获得授权时返回一致的重定向状态代码,并且当用户在帐户条中更改其帐户时,触发 2 个 AJAX 调用:一个更改帐户,然后然后通过 AJAX 转到当前页面,以检查 HTTP 状态代码。 200 OK 表示保持页面不变,Redirect 表示跟随重定向。显然这有点难看,涉及额外的 HTTP 调用,在日志中创建错误命中,并假设如何在整个应用中处理授权。
可能存在次要问题 - 页面可能已获得授权,但只需更改其工作方式或外观即可。这个特定的应用程序没有基于帐户的外观变化(除了帐户条本身),我可以通过提供一个表单监听的自定义事件来处理功能更改 - 他们可以从服务器重新加载任何相关数据以响应它。
【问题讨论】:
-
这些权限存储在哪里
-
我将扩展我的问题以举例说明我目前如何定义权限(这是标准的 MVC 东西)
标签: asp.net-mvc controller authorization roles routes