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

发布于 2024-10-27 09:04:24 字数 1121 浏览 1 评论 0原文

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

How do you make the [RequireHttps] > 如果不是 https 开头,属性会将 url 切换为 https?

我有这样的代码:

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

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

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

MVC futures 项目有一个类似的属性[RequireSsl(Redirect = true)]。但这现在已经过时了……MVC 2 中的等效项是什么?

当有人输入 URL http://example.com/home/dosomething 或 url http://example.com/home/anotheraction,我需要它们自动重定向到url http< strong>s://example.com/home/anotheraction

编辑这是事件的顺序:

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

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

I've read thru many of the questions on ASP.NET MVC [RequireHttps] - but can't find the answer to this question:

How do you make the [RequireHttps] attribute switch the url to https if it was not https to start with?

I have this code:

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

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

But I get an error saying: "The requested resource can only be accessed via SSL."

The MVC futures project has a similar attribute [RequireSsl(Redirect = true)]. But that is outdated now ... What is the equivalent in MVC 2?

When someone types in the URL http://example.com/home/dosomething OR the url http://example.com/home/anotheraction, I need them to be automatically redirected to the url https://example.com/home/anotheraction

EDIT this is the sequence of events:

The URL http://example.com/home/dosomething is called from another website. They redirect their users to this url (with a response.redirect or similar).

DoSomething() then tries to return AnotherAction(), but fails with the error message "The requested resource can only be accessed via SSL."

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

决绝 2024-11-03 09:04:24

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 会发生什么?

The RequiresHttps attribute does automatically attempt to redirect to https://your-url. I verified this behavior on a site I have that uses that attribute, and also looking at the code in 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);
}

Are you sure you have your site set up to accept secure connections? What happens if you try to browse to https://your-url directly?

2024-11-03 09:04:24

[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 相关的需求。
或访问 msdn 页面 对 request.url Absoluteuri 与 OriginalString 感到困惑?
我也是,您可以访问 dotnetperls 获取示例。
此功能使您能够在本地主机上进行开发并按原样部署代码。
现在,对于您想要进行 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);
}

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

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

[mvc 4] short answer:

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

longer answer:
to move from http to https you cant send a redirect to https after the first packet,
therefor you need to catch the packet using Application_BeginRequest,
from the Global.asax add the function and it will override the default,
the code should be something like so (Global.asax on the class level):

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://"));
  }
}

i strongly suggest putting a breakpoints and inspecting the Request.Url object for any url related need.
or visit the msdn page confused about request.url absoluteuri vs originalstring?
so am i you can go to dotnetperls for examples.
this function enables you to develop on localhost and deploying your code as is.
now for every page you want to make a https redirect you need to specify it in the if condition.
to move from https to http you can use regular Response.Redirect like so:

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

notice this also support working on the same code when developing on local host by not interrupting the original course of things pre the https addition.

also i recommend thinking about implementing some return url convention (if not already implemented) in that case you should go something like so:

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

this will redirect to the requested page post login.

naturally you should protect every page that shows user data, register, login and more.

筑梦 2024-11-03 09:04:24

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

  • Request_method:HEAD
  • User Agent:curl/7.35.0

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

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

Http HEAD requests do not appear to be redirected. When reviewing our error logs we see lots of this message, googling lands here, but after looking more at the details they have a few interesting "features"

  • Request_method: HEAD
  • User Agent: curl/7.35.0

In other words all of the failed attempts were not customer facing...

(100% credit to comment from @arserbin3 for making me realize they were all HEAD requests)

黒涩兲箜 2024-11-03 09:04:24

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);
    }
}

MVC4 does now redirect

but not how you would expect.

http://www.example.com:8080/alpha/bravo/charlie?q=quux
will be redirect the client's browser to
https://www.example.com/alpha/bravo/charlie?q=quux

Notice the lack of a port number.

http://aspnetwebstack.codeplex.com/SourceControl/latest#test/System.Web.Mvc.Test/Test/RequireHttpsAttributeTest.cs
code test
[Fact]
public void OnAuthorizationRedirectsIfRequestIsNotSecureAndMethodIsGet()

confirms this is the desired behaviour.

If you would like to write a custom attribute that does include the PORT ... you can base your code on:

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);
    }
}
紧拥背影 2024-11-03 09:04:24

为了补充已经给出的答案,这是来自 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.
    ...
}

To supplement the answer already given, this is the code from the MVC 5 implementation of HandleNonHttpsRequest

protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
    // only redirect for GET requests, otherwise the browser might not propagate the verb and request
    // body correctly.
    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文