0

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

在我的 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 以包含主机名:端口。

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

4

3 回答 3

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。请记住,虽然标头是您可以采取的重要补充措施,但最终它们留给浏览器执行,不应完全依赖。

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

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

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

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

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

Url.Action("Login", "User", null, "https", Request.Url.Host)
于 2013-02-27T18:00:52.040 回答
3

将此添加到您的 global.ascx

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

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

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

于 2014-03-24T10:34:05.763 回答
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);
    }
}
于 2014-10-14T05:10:10.613 回答