ASP.NET MVC - 阻止除搜索机器人(Googlebot,Yahoo Slurp等)之外的特定控制器的所有访问者

Cha*_*ell 5

我正在尝试为我的站点地图创建一个控制器,但只允许搜索引擎查看它.

如果你查看https://stackoverflow.com/robots.txt,你会发现他们的站点地图是https://stackoverflow.com/sitemap.xml.如果您尝试访问站点地图,您将被重定向到404页面.

这个元问题证实了这种行为(杰夫本人回答).

现在我不想把这个问题关闭为"属于Meta",因为我只是以StackOverflow为例.我真正需要回答的是......

我如何阻止所有访问控制器的访问者除了搜索机器人?

Igo*_*aka 4

您可以使用User Agent标头创建拒绝请求的过滤器属性.这个问题的用处是有问题的(并不是一个安全功能),因为标题可以很容易伪造,但它会阻止人们在股票浏览器中这样做.

此页面包含googlebot使用的用户代理字符串列表.

用于将非googlebots重定向到错误控制器上的404操作的示例代码:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class BotRestrictAttribute : ActionFilterAttribute {

    public override void OnActionExecuting(ActionExecutingContext c) {
      if (c.RequestContext.HttpContext.Request.UserAgent != "Googlebot/2.1 (+http://www.googlebot.com/bot.html)") {
        c.Result = RedirectToRouteResult("error", new System.Web.Routing.RouteValueDictionary(new {action = "NotFound", controller = "Error"}));
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑回复评论.如果服务器负载是站点地图的问题,则限制对僵尸程序的访问可能是不够的.Googlebot本身有能力在服务器决定大幅削减服务器时停止服务器.您也应该缓存响应.您可以使用相同的FilterAttributeApplication.Cache为.

这是一个非常粗略的例子,可能需要调整属性HTTP头:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class BotRestrictAttribute : ActionFilterAttribute {

    public const string SitemapKey = "sitemap";

    public override void OnActionExecuting(ActionExecutingContext c) {
      if (c.RequestContext.HttpContext.Request.UserAgent != "Googlebot/2.1 (+http://www.googlebot.com/bot.html)") {
        c.Result = RedirectToRouteResult("error", new System.Web.Routing.RouteValueDictionary(new {action = "NotFound", controller = "Error"}));
        return;
      }

      var sitemap = Application.Cache[SitemapKey];
      if (sitemap != null) {
        c.Result = new ContentResult { Content = sitemap};
        c.HttpContext.Response.ContentType = "application/xml";
      }

    }
}

//In the sitemap action method
string sitemapString = GetSitemap();
HttpContext.Current.Cache.Add(
 BotRestrictAttribute.SitemapKey, //cache key
 sitemapString, //data
 null, //No dependencies
 DateTime.Now.AddMinutes(1), 
 Cache.NoSlidingExpiration, 
 CacheItemPriority.Low, 
 null //no callback
);
Run Code Online (Sandbox Code Playgroud)