【问题标题】:ASP.Net MVC: Check if URL is AuthorizedASP.Net MVC:检查 URL 是否已授权
【发布时间】: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


【解决方案1】:

仅当您仅使用 URL 授权时,使用 UrlAuthorization.CheckUrlAccessForPrincipal 才有效。但是对于使用路由的 MVC,我们强烈建议您不要使用 URL 授权来保护应用程序。

相反,我们建议在控制器类上使用授权属性。原因是可能有多个 URL 调用相同的控制器操作。在资源处保护资源总是更好的,而不仅仅是在入口处。

在这种特殊情况下,您必须获取给定 URL 的控制器实例。这有点棘手,因为您基本上必须从拥有 URL 的位置到拥有控制器的位置运行 MVC 管道。这是可能的,但似乎重量级。

我想知道是否没有更好、更简单的方法来实现您的目标。你真正想做的是什么?

更新:根据您的情况,这听起来像是仅用于 UI 目的的初始检查。也许您需要做的就是向 URL 发出一个异步 Ajax 请求并检查 HTTP 状态代码。如果是 401 状态码,您就知道该用户未获得授权。这似乎是最安全的选择。

【讨论】:

  • 我将进一步扩展这个问题来解释目标。
【解决方案2】:

UrlAuthorizationModule.CheckUrlAccessForPrincipal 方法怎么样。

UrlAuthorizationModule.CheckUrlAccessForPrincipal Method (System.Web.Security)

【讨论】:

  • 从未尝试过这个,但它是否适用于授权不使用 ASP.NET 的典型 url-mapped-to-file funk-schwa 而是需要计算路线并弄清楚的 MVC哪个控制器和动作在起作用?
  • 创建默认的 mvc3 解决方案,并将 Home/Index.cshtml 写入 @UrlAuthorizationModule.CheckUrlAccessForPrincipal("~/Account/ChangePassword", User, "GET").allways true!嗯,对不起,不工作。
  • UrlAuthorizationModule.CheckUrlAccessForPrincipal 不检查授权属性...
  • 请注意,该方法存在安全要求,这意味着此调用在 Medium Trust 中不起作用,假设这对您来说很重要。 :)
猜你喜欢
  • 2011-08-05
  • 2017-04-23
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多