RequireHttps并路由到https URL

时间:2013-02-27 17:35:29

标签: asp.net-mvc-4 requirehttps

我在用户控制器中的大多数操作中使用RequireHttps属性来处理登录和我的安全https页面。

在我的主页上是http我有一个指向我的登录页面的链接如下(MVC 4 Razor View): -

<a href="@Url.Action("Login", "User")">Login</a>

链接正确地转到带有https地址的登录页面。但是,当我查看IIS日志时,我看到登录URL有两个条目,一个在端口80上,另一个在端口443上。

这是我应该关注的问题吗?

我知道@ Url.Action我可以强制使用https模式,但不确定这是否是最佳方法。另外这会删除端口,这在VS 2012中使用IIS Express时很烦人。然后我必须进一步扩展@ Url.Action以包含hostname:port。

所以我只是在检查(a)这应该是一个问题,(b)是否有任何其他方法强制URL为https。

3 个答案:

答案 0 :(得分:4)

大多数教程都会同意,通过使用混合模式站点(HTTP和HTTPS),您将破坏SSL的目的(某些路径需要SSL,然后切换回非SSL连接)。切换到HTTPS后,建议您强制用户继续使用HTTPS,至少在他们注销之前。我有一个使用HTTPS的站点,一旦你访问该站点,我只使用URL重写规则将用户切换到HTTPS,并且只允许使用HTTPS。

<rewrite>
  <rules>
    <rule name="Redirect HTTP to HTTPS" stopProcessing="true">
      <match url="(.*)"/>
      <conditions>
        <add input="{HTTPS}" pattern="^OFF$"/>
      </conditions>
      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther"/>
    </rule>
  </rules>
</rewrite>

执行此操作后,还建议将身份验证Cookie设置为也需要HTTPS。对于Forms身份验证,这与在web.config中设置以下内容一样简单。

<authentication>
    <forms requireSSL="true" />
</authentication>

我还建议查看一些可以设置的标题,以帮助浏览器正确处理网站,例如使用Strict-Transport-Security表示网站需要SSL。请记住,虽然标题是您可以采取的一个很好的补充措施,但最终它们留给浏览器强制执行,不应该完全依赖。

我推荐这些步骤,因为我没有遇到您所描述的症状,我希望它们能帮助解决您在日志中注意到的问题。

AMMENDMENT:哦,我也忘了提一下,与普通的旧HTTP建立连接相比,HTTPS更加密集。在宏伟的计划中并没有多少,但仍然是一些东西。我建议您使用HTTP Keep Alive以减少一些开销。

更新:通过SSL进行通信并不意味着您已通过身份验证。它只是意味着你正在通过安全/加密连接进行交谈。

以你的亚马逊为例说吧。如果您访问该网站,您只需通过HTTP获得正常连接即可。您还没有登录,只是浏览网站。如果你想要你可以切换到HTTPS,你仍然会得到相同的网站,但你还没有登录。现在,如果您尝试登录,您将被重定向,以便您通过HTTPS说话(如果您还没有),如HTTPS标记所述。即使在您实际登录后,您仍将通过SSL进行通信。 即使您尝试通过从URL的协议部分删除S而在登录时手动切换到不使用SSL,它仍然会将您发送回使用HTTPS。这是正确的方法。通常建议您在进行身份验证后不要返回非加密会话。这通常是为了避免会话劫持,因为您的身份验证cookie永远不会通过纯HTTP发送。确保您在外部资源上拥有的资源位于您信任的网站上。在HTTP连接中的外部资源访问也应该通过SSL连接。再次,因为您通过SSL进行通信并不意味着您已登录到这些来源。对于我的应用程序是100%通过SSL访问,但我也有网站上的谷歌分析和谷歌地图集成(显然两者都在我的域外)。我只是确保通过SSL与谷歌交谈。我不必实际登录Google使用任何这些东西。您的外部图像也是如此。只需确保使用HTTPS名字对象定义用于引用这些外部图像的URL,以便它使用SSL。

更新:您在日志中获得两次点击的原因是因为您正在通过HTTP请求登录链接,要求HTTPS属性点击首先意识到您没有使用SSL并使用HTTPS协议将您重定向回自身。如果你更新你的ActionLink网址,你就可以解决这个问题,但是你知道它会变得很难看。

Url.Action("Login", "User", null, "https", Request.Url.Host)

答案 1 :(得分:3)

将此添加到您的global.asax

protected void Application_BeginRequest()
        {
            if (!Context.Request.IsSecureConnection)
                Response.Redirect(Context.Request.Url.ToString().Replace

("http:", "https:"));
        }

这将导致所有请求转换为https而不是http

答案 2 :(得分:0)

我为Url.Action编写了一个扩展,根据属性修饰生成正确的协议。我让你检查

public static class Extensions
{
    public static string SecuredAction(this UrlHelper helper, string action, string controller)
    {
        bool requireSSL = false;
        var route = System.Web.Routing.RouteTable.Routes.Select(r => r as System.Web.Routing.Route) .Where(r =>
            r != null && r.Defaults != null && r.Defaults["controller"] != null && r.Defaults["controller"].ToString().Equals(controller, StringComparison.InvariantCultureIgnoreCase)
            && r.Defaults["action"] != null && r.Defaults["action"].ToString().Equals(action, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

        if(route == null)
            return helper.Action(action, controller);

        //Get the method and check if requiere ssl
        MemberInfo method = route.DataTokens["TargetActionMethod"] as MemberInfo;
        requireSSL = method.CustomAttributes.Any(a => a.AttributeType == typeof(RequireHttps)) || method.DeclaringType.CustomAttributes.Any(a => a.AttributeType == typeof(RequireHttps));

        //Return the correct protocol
        if(helper.RequestContext.HttpContext.Request.IsSecureConnection && !requireSSL)
            return helper.Action(action, controller, null, "http");

        if (!helper.RequestContext.HttpContext.Request.IsSecureConnection && requireSSL)
            return helper.Action(action, controller, null, "https");

        return helper.Action(action, controller);
    }
}