8 Stimmen

Bewegen zwischen HTTP und HTTPS in ASP.NET MVC

Also habe ich das [RequiresHttps] Attribut gefunden, aber einmal in https stecken Sie irgendwie fest, also habe ich versucht, Aktionen auf einer einzigen URL (und Schema) durchführen zu können, habe ich festgestellt, dass ich meinen eigenen ExtendedController erstellen musste, um für Aktionen, die nicht [RequireHttps] verwenden, wieder auf http zurückzukehren.

Ich frage mich nur, ob das, was ich mache, in Ordnung ist oder ob es einen besseren Weg gibt?

public class ExtendedController : Controller
{
    protected virtual void HandleHttpRequest(AuthorizationContext filterContext)
    {
        if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("Kann nicht zwischen https und http posten.");
        }
        string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url);
    }

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        object[] attributes = filterContext.ActionDescriptor.GetCustomAttributes(true);
        if (!attributes.Any(a => a is RequireHttpsAttribute))
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.HttpContext.Request.IsSecureConnection)
            {
                this.HandleHttpRequest(filterContext);
            }
        }
    }
}

11voto

Clicktricity Punkte 4138

Was Sie haben, ist syntaktisch korrekt, jedoch wäre es ratsam, einen neuen Aktionsfilter zu erstellen, der von dem standardmäßigen RequireHttpsAttribute erbt und einen Parameter erhält, um zwischen http und https zu wechseln.

public class RequireHttpsAttribute : System.Web.Mvc.RequireHttpsAttribute
{
    public bool RequireSecure = false;

    public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)

    {
        if (RequireSecure)
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            // nicht sichere Anfrage
            if (filterContext.HttpContext.Request.IsSecureConnection)
            {
                HandleNonHttpRequest(filterContext);
            }
        }
    }

    protected virtual void HandleNonHttpRequest(AuthorizationContext filterContext)
    {
        if (String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            // Weiterleitung zur HTTP-Version der Seite
            string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
            filterContext.Result = new RedirectResult(url);
        }
    } 
}

Dann würden Sie in Ihrer Aktionsmethode oder Controller verwenden:

[RequireHttps (RequireSecure = true)]

...

oder

[RequireHttps (RequireSecure = false)]

1voto

Arvind Dhasmana Punkte 1336

Um es etwas übersichtlicher zu machen. Diese Lösung geht davon aus, dass die Mehrheit Ihrer Webanwendung das HTTP-Schema verwendet.

  1. Erstellen Sie einen neuen Aktionsfilter RequiresHttp (verwenden Sie HTTP, wenn das NeedSsl-Attribut nicht explizit auf Aktion oder Controller angewendet wird),

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        HttpRequestBase req = filterContext.HttpContext.Request;
        HttpResponseBase res = filterContext.HttpContext.Response;
    
        bool needSsl = filterContext.ActionDescriptor.IsDefined(typeof(NeedSslAttribute), true)
                        || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(NeedSslAttribute), true);
    
        if (needSsl && !req.IsSecureConnection) //https: sicher
        {
            var builder = new UriBuilder(req.Url)
            {
                Scheme = Uri.UriSchemeHttps,
                Port = 444
            };
            res.Redirect(builder.Uri.ToString());
        }
        else if (!needSsl && req.IsSecureConnection) //http: nicht sicher
        {
            var builder = new UriBuilder(req.Url)
            {
                Scheme = Uri.UriSchemeHttp,
                Port = 8081
            };
            res.Redirect(builder.Uri.ToString());
        }
        base.OnActionExecuting(filterContext);
    }
  2. Und neues leeres Attribut NeedSSL (zu Anzeigezwecken)

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class NeedSslAttribute : Attribute { }
  3. Wenden Sie RequiresHttp als globalen Aktionsfilter in Global.aspx.cs an

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new RequiresHttp());
    }
  4. Wenden Sie jetzt NeedSslAttribute auf Controller und Aktionen an, bei denen Sie das HTTPS-Schema verwenden möchten

    [NeedSsl]
    [AllowAnonymous]
    public ActionResult LogOn()

Dieser Code ist nicht perfekt, da der Aktionsfilter RequiresHttp mehrere Aufgaben erledigt, d.h. das Überprüfen des NeedSsl-Attributs und das Anwenden des HTTP- oder HTTPS-Schemas. Es wäre besser gewesen, wenn wir zwei Aktionsfilter RequiresHTTP and RequiresHTTPS verwenden könnten.

Jetzt, wenn RequiresHTTP als globaler Filter festgelegt wäre und der RequiresHTTPS-Filter auf bestimmte Aktionen angewendet würde, hätte der spezifische RequiresHTTPS-Filter den Vorrang.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X