1

我想用 http 和 https 绑定来托管我的 ASP.NET MVC 网站。但是只有少数路径应该可以通过 http 获得,而所有路径都应该可以通过 https 获得。

例如,我的应用程序公开了以下 url:

https://server/v1/setup
https://server/v1/exchange
https://server/v1/time

我希望时间 url 也可以通过 http 获得

http://server/v1/time

我不想在 IIS 中设置任何规则。有什么方法可以控制通过 http 在代码中可用的 url?

我还查看了 RequiresHttps 属性,但它存在一些重定向问题。如果对不允许的路径发出 http 请求,则响应应为 404(未找到)。

4

3 回答 3

3

您可以制作一个动作过滤器来检查 https。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class HttpsOnlyAttribute : ActionFilterAttribute
{
    /// <summary>
    /// Called by the MVC framework before the action method executes.
    /// </summary>
    /// <param name="filterContext">The filter context.</param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!filterContext.HttpContext.Request.IsSecureConnection)
        {
            throw new HttpException(404, "HTTP/1.1 404 Not Found");
        }
    }
}

只需将属性放在您只想成为 https 的控制器的顶部

[HttpsOnly]
public class SecureController : Controller
{
     // your actions here
}

您甚至可以只针对操作

public class SampleController : Controller
{
    [HttpsOnly]
    public ActionResult SecureAction()
    {
        return View();
    }
}
于 2013-06-13T14:15:06.800 回答
1

在这种情况下仍可以使用RequireHttpsAttribute 。

用它装饰你的动作控制器会将 GET 请求重定向到安全版本,并为所有其他方法抛出错误。

如果您从此方法扩展,您可以覆盖处理以始终返回 404,或使用默认处理。

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class RequireHttpsExtendedAttribute : RequireHttpsAttribute
{
    public RequireHttpsExtendedAttribute(bool throwNotFound = false)
    {
        ThrowNotFound = throwNotFound;
    }

    private bool ThrowNotFound { get; set; }

    protected override void HandleNonHttpsRequest(AuthorizationContext filterContext)
    {
        if (ThrowNotFound)
            throw new HttpException(404, "HTTP/1.1 404 Not Found");

        base.HandleNonHttpsRequest(filterContext);
    }
}
于 2013-06-13T14:37:37.787 回答
0

感谢您的回复!我想出了使用自定义路由约束的解决方案。

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Test1_default",
            "Test1/CurrentTime",
            new { action = "CurrentTime", controller = "Default1" },
            new { https = new HttpsConstraint() });
    }
}

public class HttpsConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        return httpContext.Request.IsSecureConnection;
    }
}
于 2013-06-21T07:35:04.883 回答