13

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

[RequireHttps]如果不是以 https 开头,如何使属性将 url 切换为 https?

我有这个代码:

public ActionResult DoSomething()
{
    return View("AnotherAction");
}

[RequireHttps]
public ActionResult AnotherAction()
{
    return View();
}

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

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

当有人输入网址http://example.com/home/dosomething或网址http://example.com/home/anotheraction时,我需要将他们自动重定向到网址http://example.com /home/另一个动作

编辑这是事件的顺序:

URL http://example.com/home/dosomething是从另一个网站调用的。他们将用户重定向到这个 url(使用 response.redirect 或类似的)。

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

4

5 回答 5

23

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直接浏览会发生什么?

于 2011-03-27T05:21:03.457 回答
15

[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 对象是否有任何与 url 相关的需求。
或访问对 request.url absoluteuri 与 originalstring 混淆的msdn 页面?
我也是,你可以去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 之前中断原始进程。

我还建议考虑实施一些返回 url 约定(如果尚未实施),在这种情况下你应该这样做:

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

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

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

于 2013-07-29T23:11:14.273 回答
3

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

  • 请求方法:HEAD
  • 用户代理:curl/7.35.0

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

(100% 归功于 @arserbin3 的评论让我意识到他们都是HEAD请求)

于 2016-07-28T14:09:04.723 回答
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);
    }
}
于 2015-02-24T05:31:47.027 回答
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.
    ...
}
于 2014-02-04T21:46:28.313 回答