Frage

Wie gehe ich über die Verwendung von HTTPS für einige der Seiten in meiner ASP.NET MVC-basierten Website?

Steve Sanderson hat eine ziemlich gute Anleitung, wie man dies in einer trockenen Art und Weise zu tun, auf Vorschau 4 an:

http: // blog .codeville.net / 2008/08/05 / Additions-httpsssl-Support-to-aspnet-mvc-Routing /

Gibt es eine bessere / aktualisierte Art und Weise mit Vorschau 5?,

War es hilfreich?

Lösung

Wenn Sie ASP.NET MVC 2 Preview 2 oder höher , können Sie jetzt einfach verwenden:

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

Obwohl der Ordnungsparameter ist bemerkenswert, wie

Andere Tipps

MVCFutures hat ein 'RequireSSL' Attribut.

(dank Adams für dass Hinweis auf in Ihrer aktualisierten Blogpost )

Wenden Sie einfach es auf Ihre Aktion-Methode, mit 'Redirect = true', wenn Sie eine http wollen: // Anforderung automatisch https werden: //:

    [RequireSsl(Redirect = true)]

Siehe auch: ASP.NET MVC RequireHttps in Produktion Nur

Wie Amadiere schrieb [RequireHttps] funktioniert super in MVC 2 für Eingabe HTTPS. Aber wenn Sie HTTPS verwenden möchten für einige Seiten, wie Sie gesagt haben, ist MVC 2 Sie keine Liebe geben - wenn es einen Benutzer zu HTTPS-Schalter sind sie dort stecken, bis Sie sie manuell umleiten.

Der Ansatz, den ich verwendet wird, ist ein anderes benutzerdefiniertes Attribut zu verwenden, [ExitHttpsIfNotRequired]. Bei Anschluss an einen Controller oder Aktion angebracht wird diese Umleitung auf HTTP, wenn:

  1. Die Anforderung war HTTPS
  2. Die [RequireHttps] Attribut wurde nicht auf die Aktion (oder Controller) angewendet
  3. Die Anforderung war ein GET (ein POST-Umleitung zu allen möglichen Problemen führen würde).

Es ist ein bisschen zu groß, um eine Nachricht schreiben, aber man kann einen href sehen <= „http://lukesampson.com/post/471548689/entering-and-exiting-https-with-asp-net-mvc“ rel = "nofollow noreferrer"> der Code hier sowie einige zusätzliche Details.

Hier ist ein kürzlich erschienener Beitrag von Dan Wahlin dazu:

http://weblogs.asp.net/dwahlin/archive/2009/08/25/requiring-ssl-for-asp-net-mvc-controllers.aspx

Er verwendet ein Action Attribut.

Einige Action Erweiterungen: http: // www .squaredroot.com / Post / 2008/06/11 / MVC-and-SSL.aspx Oder ein Controller-Aktion Attribut, das auf https umgeleitet: // http: // Foren. asp.net/p/1260198/2358380.aspx#2358380

Für diejenigen, die kein Fan von Attribut-orientierte Entwicklungsansätze sind, hier ist ein Stück Code, das helfen könnte:

public static readonly string[] SecurePages = new[] { "login", "join" };
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
    var pageName = RequestHelper.GetPageNameOrDefault();
    if (!HttpContext.Current.Request.IsSecureConnection
        && (HttpContext.Current.Request.IsAuthenticated || SecurePages.Contains(pageName)))
    {
        Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"] + HttpContext.Current.Request.RawUrl);
    }
    if (HttpContext.Current.Request.IsSecureConnection
        && !HttpContext.Current.Request.IsAuthenticated
        && !SecurePages.Contains(pageName))
    {
        Response.Redirect("http://" + Request.ServerVariables["HTTP_HOST"] + HttpContext.Current.Request.RawUrl);
    }
}

Es gibt mehrere Gründe Attribute zu vermeiden, und einer von ihnen ist, wenn man sich die Liste aller gesicherten Seiten suchen wollen, werden Sie alle Controller in Lösung springen müssen.

ich accross diese Frage ging und hoffe, dass meine Lösung kann jemand hilft.

Wir haben einige Probleme:  - Wir brauchen spezifische Maßnahmen zu sichern, zum Beispiel „logon“ in „Account“. Wir können die Build verwenden in RequireHttps Attribut, das ist toll - aber es wird uns mit https Umleitung zurück: //.  -. Wir sollten unsere Links, Formulare und solche "SSL aware"

machen

Im Allgemeinen meine Lösung ermöglicht Routen angeben, die absolute URL verwenden, zusätzlich zu der Fähigkeit, das Protokoll zu spezifizieren. Sie können diese approch verwenden Sie das „https“ Protokoll angeben.

Also, erstens habe ich eine ConnectionProtocol Enum erstellt:

/// <summary>
/// Enum representing the available secure connection requirements
/// </summary>
public enum ConnectionProtocol
{
    /// <summary>
    /// No secure connection requirement
    /// </summary>
    Ignore,

    /// <summary>
    /// No secure connection should be used, use standard http request.
    /// </summary>
    Http,

    /// <summary>
    /// The connection should be secured using SSL (https protocol).
    /// </summary>
    Https
}

Jetzt habe ich von Hand gerollt Version von RequireSSL erstellt. Ich habe die ursprüngliche RequireSSL Quellcode geändert Umleitung zu http zuzulassen zurück: // URLs. Darüber hinaus habe ich ein Feld setzen, die uns, wenn wir SSL erfordern sollten bestimmen können, oder nicht (ich verwende es mit dem DEBUG Pre-Prozessor).

/* Note:
 * This is hand-rolled version of the original System.Web.Mvc.RequireHttpsAttribute.
 * This version contains three improvements:
 * - Allows to redirect back into http:// addresses, based on the <see cref="SecureConnectionRequirement" /> Requirement property.
 * - Allows to turn the protocol scheme redirection off based on given condition.
 * - Using Request.IsCurrentConnectionSecured() extension method, which contains fix for load-balanced servers.
 */
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public sealed class RequireHttpsAttribute : FilterAttribute, IAuthorizationFilter
{
    public RequireHttpsAttribute()
    {
        Protocol = ConnectionProtocol.Ignore;
    }

    /// <summary>
    /// Gets or sets the secure connection required protocol scheme level
    /// </summary>
    public ConnectionProtocol Protocol { get; set; }

    /// <summary>
    /// Gets the value that indicates if secure connections are been allowed
    /// </summary>
    public bool SecureConnectionsAllowed
    {
        get
        {
#if DEBUG
            return false;
#else
            return true;
#endif
        }
    }

    public void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        /* Are we allowed to use secure connections? */
        if (!SecureConnectionsAllowed)
            return;

        switch (Protocol)
        {
            case ConnectionProtocol.Https:
                if (!filterContext.HttpContext.Request.IsCurrentConnectionSecured())
                {
                    HandleNonHttpsRequest(filterContext);
                }
                break;
            case ConnectionProtocol.Http:
                if (filterContext.HttpContext.Request.IsCurrentConnectionSecured())
                {
                    HandleNonHttpRequest(filterContext);
                }
                break;
        }
    }


    private 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("The requested resource can only be accessed via SSL.");
        }

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

    private void HandleNonHttpRequest(AuthorizationContext filterContext)
    {
        if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("The requested resource can only be accessed without SSL.");
        }

        // redirect to HTTP version of page
        string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url);
    }
}

Nun, dies RequireSSL die folgende Basis tun auf Ihrem Bedarf Attributwert:  Ignorieren -: Wird nichts nicht tun.  - Http: Wird Umleitung auf HTTP-Protokoll erzwingen.  - Https:. Wird die Umleitung zu HTTPS-Protokoll erzwingen

Sie sollten Ihre eigenen Basis-Controller und dieses Attribut auf Http erstellen.

[RequireSsl(Requirement = ConnectionProtocol.Http)]
public class MyController : Controller
{
    public MyController() { }
}

Nun, in jedem cpntroller / Aktion möchten Sie SSL erforderlich -. Setzen gerade dieses Attribut mit ConnectionProtocol.Https

Jetzt kann URLs bewegen: Wir haben einige Probleme mit dem URL-Routing-Engine. Sie können mehr über sie unter http lesen : //blog.stevensanderson.com/2008/08/05/adding-httpsssl-support-to-aspnet-mvc-routing/ . Die Lösung in diesem Beitrag vorgeschlagen ist theoreticly gut, aber alt und ich weiß nicht wie die approch.

Meine Lösungen ist die folgende: Erstellen Sie eine Unterklasse der Grund „Route“ Klasse:

public class AbsoluteUrlRoute: Route     {         #region Ctor

    /// <summary>
    /// Initializes a new instance of the System.Web.Routing.Route class, by using
    ///     the specified URL pattern and handler class.
    /// </summary>
    /// <param name="url">The URL pattern for the route.</param>
    /// <param name="routeHandler">The object that processes requests for the route.</param>
    public AbsoluteUrlRoute(string url, IRouteHandler routeHandler)
        : base(url, routeHandler)
    {

    }

    /// <summary>
    /// Initializes a new instance of the System.Web.Routing.Route class, by using
    ///     the specified URL pattern and handler class.
    /// </summary>
    /// <param name="url">The URL pattern for the route.</param>
    /// <param name="defaults">The values to use for any parameters that are missing in the URL.</param>
    /// <param name="routeHandler">The object that processes requests for the route.</param>
    public AbsoluteUrlRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
        : base(url, defaults, routeHandler)
    {

    }

    /// <summary>
    /// Initializes a new instance of the System.Web.Routing.Route class, by using
    ///     the specified URL pattern and handler class.
    /// </summary>
    /// <param name="url">The URL pattern for the route.</param>
    /// <param name="defaults">The values to use for any parameters that are missing in the URL.</param>
    /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param>
    /// <param name="routeHandler">The object that processes requests for the route.</param>
    public AbsoluteUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints,
                            IRouteHandler routeHandler)
        : base(url, defaults, constraints, routeHandler)
    {

    }

    /// <summary>
    /// Initializes a new instance of the System.Web.Routing.Route class, by using
    ///     the specified URL pattern and handler class.
    /// </summary>
    /// <param name="url">The URL pattern for the route.</param>
    /// <param name="defaults">The values to use for any parameters that are missing in the URL.</param>
    /// <param name="constraints">A regular expression that specifies valid values for a URL parameter.</param>
    /// <param name="dataTokens">Custom values that are passed to the route handler, but which are not used
    ///     to determine whether the route matches a specific URL pattern. These values
    ///     are passed to the route handler, where they can be used for processing the
    ///     request.</param>
    /// <param name="routeHandler">The object that processes requests for the route.</param>
    public AbsoluteUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints,
                            RouteValueDictionary dataTokens, IRouteHandler routeHandler)
        : base(url, defaults, constraints, dataTokens, routeHandler)
    {

    }

    #endregion

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
    {
        var virtualPath = base.GetVirtualPath(requestContext, values);
        if (virtualPath != null)
        {
            var scheme = "http";
            if (this.DataTokens != null && (string)this.DataTokens["scheme"] != string.Empty)
            {
                scheme = (string) this.DataTokens["scheme"];
            }

            virtualPath.VirtualPath = MakeAbsoluteUrl(requestContext, virtualPath.VirtualPath, scheme);
            return virtualPath;
        }

        return null;
    }

    #region Helpers

    /// <summary>
    /// Creates an absolute url
    /// </summary>
    /// <param name="requestContext">The request context</param>
    /// <param name="virtualPath">The initial virtual relative path</param>
    /// <param name="scheme">The protocol scheme</param>
    /// <returns>The absolute URL</returns>
    private string MakeAbsoluteUrl(RequestContext requestContext, string virtualPath, string scheme)
    {
        return string.Format("{0}://{1}{2}{3}{4}",
                             scheme,
                             requestContext.HttpContext.Request.Url.Host,
                             requestContext.HttpContext.Request.ApplicationPath,
                             requestContext.HttpContext.Request.ApplicationPath.EndsWith("/") ? "" : "/",
                             virtualPath);
    }

    #endregion
}

Diese Version von "Route" Klasse wird absolute URL erstellen. Der Trick hier, durch den Blog-Post Autor Vorschlag gefolgt, ist die DataToken zu verwenden, um das Schema (Beispiel am Ende :)) angeben.

Wenn wir nun eine URL generieren werden, zum Beispiel für die Route "Konto / logon" wir bekommen "/

<httpModules>
  <!-- Removing the default UrlRoutingModule and inserting our own absolute url routing module -->
  <remove name="UrlRoutingModule-4.0" />
  <add name="UrlRoutingModule-4.0" type="MyApp.Web.Mvc.Routing.AbsoluteUrlRoutingModule" />
</httpModules>

Das ist es.)

Um ein absolutes / Protokoll gefolgt Route zu registrieren, sollten Sie tun:

        routes.Add(new AbsoluteUrlRoute("Account/LogOn", new MvcRouteHandler())
            {
                Defaults = new RouteValueDictionary(new {controller = "Account", action = "LogOn", area = ""}),
                DataTokens = new RouteValueDictionary(new {scheme = "https"})
            });

Wird die Liebe Feedback + Verbesserungen zu hören. Hoffe, dass es helfen kann! :)

Edit: Ich habe die IsCurrentConnectionSecured () Erweiterungsmethode (zu viele Schnipsel: P) aufzunehmen. Dies ist eine Erweiterung Methode, die im allgemeinen verwendet Request.IsSecuredConnection. Dies wird jedoch approch nicht funktionieren, wenn Load-Balancing mit -. So dass diese Methode kann dies umgehen (von nopCommerce nahm)

    /// <summary>
    /// Gets a value indicating whether current connection is secured
    /// </summary>
    /// <param name="request">The base request context</param>
    /// <returns>true - secured, false - not secured</returns>
    /// <remarks><![CDATA[ This method checks whether or not the connection is secured.
    /// There's a standard Request.IsSecureConnection attribute, but it won't be loaded correctly in case of load-balancer.
    /// See: <a href="http://nopcommerce.codeplex.com/SourceControl/changeset/view/16de4a113aa9#src/Libraries/Nop.Core/WebHelper.cs">nopCommerce WebHelper IsCurrentConnectionSecured()</a>]]></remarks>
    public static bool IsCurrentConnectionSecured(this HttpRequestBase request)
    {
        return request != null && request.IsSecureConnection;

        //  when your hosting uses a load balancer on their server then the Request.IsSecureConnection is never got set to true, use the statement below
        //  just uncomment it
        //return request != null && request.ServerVariables["HTTP_CLUSTER_HTTPS"] == "on";
    }

Hier ist ein Blog-Eintrag von Pablo M. Cibrano ab Januar 2009, die ein paar Techniken, einschließlich einem Httpmodule und Erweiterungsmethoden einsammelt.

Hier ist ein Blog-Eintrag von Adam Salvo rel="nofollow dass ein Actionfilter verwendet .

Dies ist nicht unbedingt MVC spezifisch, aber diese Lösung funktioniert für beide ASP.NET WebForms und MVC:

http://www.codeproject.com/KB/web-security /WebPageSecurity_v2.aspx

Ich habe dies seit mehreren Jahren verwendet und wie die Trennung von Bedenken und Management über die web.config-Datei.

MVC 6 (ASP.NET Core-1.0) arbeitet etwas anders mit Startup.cs.

RequireHttpsAttribute verwenden (wie in von Amadiere antworten) auf allen Seiten, können Sie dies in Startup.cs hinzufügen statt auf jedem Controller Attribut Stil (oder statt der Schaffung einer Base für alle Steuerungen von erben).

Startup.cs - Register Filter:

public void ConfigureServices(IServiceCollection services)
{
    // TODO: Register other services

    services.AddMvc(options =>
    {
        options.Filters.Add(typeof(RequireHttpsAttribute));
    });
}

Für weitere Informationen über Design-Entscheidungen für obigen Ansatz, siehe meine Antwort auf ähnliche Frage zu wie localhost Anfragen auszuschließen aus durch die gehandhabt wird RequireHttpsAttribute .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top