【问题标题】:Deny direct URL access to action method拒绝对操作方法的直接 URL 访问
【发布时间】:2011-12-01 05:11:26
【问题描述】:

我正在尝试找到一种方法来拒绝对我的操作方法的任何直接访问。基本上,我希望我的用户点击链接进行导航,而不是直接在浏览器的地址栏中输入 URL。

现在我知道这可以通过检查请求对象中的 urlreferrer 来完成,但这有点不可靠和弱,因为 urlreferrer 很容易被修改,并且一些安全套件实际上将它从请求中删除。

那么你们中的任何人都知道在 asp.net mvc3 中执行此操作的方法吗?

【问题讨论】:

  • 这需要有多“安全”?您是否只想阻止用户添加书签和/或键入 URL?或者你真的想让它免受那些真正知道如何欺骗 Javascript 和 cookie 的人的攻击吗?
  • 我想让它尽可能安全,这就是为什么 urlreferrer 不太适合,因为它很容易被欺骗
  • 这是为了防止CSRF吗?还是您真的需要防止“授权”用户欺骗有效请求?
  • 这与 CSRF 无关,我们确实为此使用了 ValidateAntiForgeryToken 属性。我们希望阻止所有用户(包括“授权”用户)直接访问操作方法!唯一可以访问的 URL 是 domain/Login

标签: c# asp.net-mvc asp.net-mvc-3


【解决方案1】:

下面是 NoDirectAccessAttribute 方法的代码,用于限制对应用 NoDirectAccess 属性的任何类或操作方法的直接访问

using System;
using System.Web.Mvc;
using System.Web.Routing;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class NoDirectAccessAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.UrlReferrer == null || 
                    filterContext.HttpContext.Request.Url.Host != filterContext.HttpContext.Request.UrlReferrer.Host)
            {
            filterContext.Result = new RedirectToRouteResult(new
                           RouteValueDictionary(new { controller = "Home", action = "Index", area = "" }));  
        }
    }
}

对不希望用户直接请求的任何控制器或操作方法使用如下操作过滤器

[NoDirectAccess]
public ActionResult IsUsernameUnique()

在上面的示例中,对 IsUsernameUnique 操作方法的任何直接访问都会自动将用户重定向到 Home/Index 操作方法。

【讨论】:

  • 好朋友!非常感谢。
【解决方案2】:

我不确定,但也许这可以帮助你 考虑我们有一个带有这个 url 的页面

www.yoursite.com/home.aspx

为了避免您的用户直接浏览此页面,您可以像这样重写您的 url

www.yoursite.com/fdmf489ruv30/home.aspx

在这个网址中,“fdmf489ruv30”部分是您在 session_start 上创建的唯一字符串,并将在 session_end 上销毁它

【讨论】:

  • 这是个好主意。但是如果唯一 id 是一个查询字符串,它不是同样有效吗?
  • 我真的不想这样做,因为这会使网址变得混乱并且对 seo 不友好。
  • 是的,对 SEO 来说是个坏主意(尝试通过其他 SEO 概念在 google 中获得更好的排名)。关于查询字符串,我没有测试我的 self.try 并告诉我结果
  • 如果您无论如何都阻止访问,那么搜索引擎优化确实不是问题,因为爬虫无论如何都无法访问这些。但是,为了清洁起见,我也会避免这种方法
【解决方案3】:

不可能安全地确保授权用户不能欺骗有效请求。
毕竟,如果浏览器可以创建“有效请求”,那么授权用户也可以

但是,这是一个不寻常的要求,我很想知道它背后的动机是什么?

不过,有很多方法可以让请求更难被欺骗。
由于没有任何方法是完全安全的,因此您可以尝试混淆,让别人欺骗您的请求乏味

正如其他人所建议的那样,您可以为每个会话创建一个随机“令牌”并在 URL 中要求它(作为路径或查询字符串)。

为此使用 JavaScript 会更好。使用此“令牌”渲染隐藏的输入。然后,拦截每个链接的click 事件,将“令牌”值附加到 URL,然后导航到 URL。

您可以增强 JavaScript 以在使用令牌之前以某种方式“处理”您的令牌,并缩小您的 JavaScript 以混淆它……这肯定会阻止高于平均水平的用户修改您的 URL。

有很多可能的解决方案,但“正确”的解决方案实际上取决于您要防止的具体行为。

【讨论】:

  • 同意这一点。你想达到什么目的?您可以创建一个全局 html 页面容器并使用基于 ajax 的操作返回您嵌入的 html。 Ajax 操作可以通过属性或其他隐藏令牌方式限制直接 url 访问。
【解决方案4】:

在 Global.asax.cs 中使用此代码并向所有控制器调用 [NoDirectAccess]

    //Prevent direct URL access: Call [NoDirectAccess] to all controllers to block
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class NoDirectAccessAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.UrlReferrer == null ||
                        filterContext.HttpContext.Request.Url.Host != filterContext.HttpContext.Request.UrlReferrer.Host)
            {
                filterContext.Result = new RedirectToRouteResult(new
                               RouteValueDictionary(new { controller = "Home", action = "Login", area = "" }));
            }
        }
    }

【讨论】:

    【解决方案5】:

    一种快速的方法是在重定向的动作中设置一个包含随机数的会话,并将随机数作为参数传递给另一个动作。

    在另一个action(redirected one)里面,比较session的值和action的参数。如果值相等,则用户通过按下按钮到达那里,否则,用户通过更改 URL 到达那里。希望对您有所帮助。

    question on Stackoverflow

    【讨论】:

      猜你喜欢
      • 2015-09-02
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 1970-01-01
      • 2011-11-09
      • 2014-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多