MVC RequireHttps并重定向,如果不是https

时间:2011-03-27 04:31:28

标签: c# asp.net-mvc-2 ssl requirehttps

我已经阅读了很多关于ASP.NET MVC [RequireHttps]的问题 - 但找不到这个问题的答案:

如果将[RequireHttps]属性设置为https(如果不是https),如何将public ActionResult DoSomething() { return View("AnotherAction"); } [RequireHttps] public ActionResult AnotherAction() { return View(); } 属性切换为https?

我有这段代码:

[RequireSsl(Redirect = true)]

但是我收到一条错误消息:“所请求的资源只能通过SSL访问。”

MVC期货项目具有类似的属性DoSomething()。但现在已经过时了... MVC 2中的等价物是什么?

如果有人在网址http://example.com/home/dosomething或网址http://example.com/home/anotheraction中输入内容,我需要将其自动重定向到网址 s :// example@home / anotheraction

编辑这是一系列事件:

从其他网站调用网址http://example.com/home/dosomething。他们将用户重定向到此网址(使用response.redirect或类似网址)。

AnotherAction()然后尝试返回{{1}},但失败并显示错误消息“只能通过SSL访问所请求的资源。”

5 个答案:

答案 0 :(得分:21)

RequiresHttps属性会自动尝试重定向到https://your-url。我在使用该属性的网站上验证了此行为,并查看了Reflector中的代码:

protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
    if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
    {
        throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl);
    }
    string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
    filterContext.Result = new RedirectResult(url);
}

您确定要将您的网站设置为接受安全连接吗?如果您尝试直接浏览https://your-url会怎样?

答案 1 :(得分:14)

[mvc 4]简答:

protected void Application_BeginRequest(Object source, EventArgs e)
{
  if (!Context.Request.IsSecureConnection)
  {
      Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://"));
  }
}

更长的回答:
要从http移动到https,你不能在第一个数据包后发送重定向到https,
因此,您需要使用Application_BeginRequest来捕获数据包,
从Global.asax添加函数,它将覆盖默认值,
代码应该是这样的(类级别的Global.asax):

protected void Application_BeginRequest(Object source, EventArgs e)
{
  if (!Context.Request.IsSecureConnection && 
      !Request.Url.Host.Contains("localhost") && 
      Request.Url.AbsolutePath.Contains("SGAccount/Login"))
  {
      Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://"));
  }
}

我强烈建议设置一个断点并检查Request.Url对象是否有任何与网址相关的需求 或者访问msdn page混淆request.url absoluteuri vs originalalstring?
所以我可以去dotnetperls 举例 此功能使您可以在localhost上进行开发并按原样部署代码 现在,对于要进行https重定向的每个页面,您需要在if条件中指定它 要从https移动到http,您可以使用常规的Response.Redirect,如下所示:

if (Request.Url.Scheme.Contains("https"))
{
    Response.Redirect(string.Format("http://{0}", Request.Url.Authority), true);
}

请注意,这也支持在本地主机上进行开发时使用相同的代码,而不会在https添加之前中断原始过程。

我还建议考虑实现一些返回网址约定(如果尚未实现),那么你应该这样做:

if (Request.Url.Scheme.Contains("https"))
{
    Response.Redirect(string.Format("http://{0}{1}", Request.Url.Authority, returnUrl), true);
}

这将在登录后重定向到请求的页面。

当然,您应该保护每个显示用户数据,注册,登录等的页面。

答案 2 :(得分:3)

Http HEAD 请求似乎未被重定向。在查看我们的错误日志时,我们看到了很多这样的消息,谷歌在这里搜索,但在仔细查看细节后,他们有一些有趣的“功能”

  • Request_method: HEAD
  • 用户代理:curl / 7.35.0

换句话说,所有失败的尝试都不是面向客户......

(100%赞成来自@ arserbin3的评论让我意识到他们都是 HEAD 请求)

答案 3 :(得分:2)

MVC4现在重定向

但不是你期望的。

http://www.example.com:8080/alpha/bravo/charlie?q=quux 将客户端的浏览器重定向到 https://www.example.com/alpha/bravo/charlie?q=quux

请注意缺少端口号。

http://aspnetwebstack.codeplex.com/SourceControl/latest#test/System.Web.Mvc.Test/Test/RequireHttpsAttributeTest.cs 代码测试         [事实]         public void OnAuthorizationRedirectsIfRequestIsNotSecureAndMethodIsGet()

确认这是理想的行为。

如果您想编写包含PORT的自定义属性...您可以将代码基于:

http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RequireHttpsAttribute.cs

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter
{
    public RequireHttpsAttribute()
        : this(permanent: false)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="RequireHttpsAttribute"/> class.
    /// </summary>
    /// <param name="permanent">Whether the redirect to HTTPS should be a permanent redirect.</param>
    public RequireHttpsAttribute(bool permanent)
    {
        this.Permanent = permanent;
    }

    /// <summary>
    /// Gets a value indicating whether the redirect to HTTPS should be a permanent redirect.
    /// </summary>
    public bool Permanent { get; private set; }

    public virtual void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (!filterContext.HttpContext.Request.IsSecureConnection)
        {
            HandleNonHttpsRequest(filterContext);
        }
    }

    protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
    {
        // only redirect for GET requests, otherwise the browser might not propagate the verb and request
        // body correctly.

        if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl);
        }

        // redirect to HTTPS version of page
        string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url, this.Permanent);
    }
}

答案 4 :(得分:0)

为了补充已经给出的答案,这是来自HandleNonHttpsRequest的MVC 5实现的代码

protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
    // only redirect for GET requests, otherwise the browser might not propagate the verb and request
    // body correctly.
    ...
}