2010-07-19 13 views
52

Czytałem poprzednie posty dotyczące korzystania z RequireHttpsAttribute zabezpieczyć poszczególne kontrolery:MVC RequireHttps cała witryna

ASP.NET MVC RequireHttps in Production Only

ale czy jest jakiś sposób, aby zastosować to do całej witryny? Z powodu mojego hosta (discountasp.net) nie mogę użyć ustawienia "RequireSSL IIS".

+0

Polecam niestandardowy moduł przekierowania, ponieważ szybciej go złapie i przekieruje w cyklu życia mvc. Robiłbym to inaczej niż ten artykuł [http://alexwolfthoughts.com/efficient-mvc-redirects-using-an-http-module], ale pokazuje niektóre z możliwości. – christo8989

Odpowiedz

20

I skończył przy użyciu IIS URL Przepisz 2.0 zmusić stronę, aby przełączyć się do HTTPS. Ten kod w pliku web.config rozwiązuje problem:

<system.webServer> 
    <!-- This uses URL Rewrite 2.0 to force the entire site into SSL mode --> 
    <rewrite xdt:Transform="Insert"> 
     <rules> 
     <rule name="Force HTTPS" enabled="true"> 
      <match url="(.*)" ignoreCase="false" /> 
      <conditions> 
      <add input="{HTTPS}" pattern="off" /> 
      </conditions> 
      <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" /> 
     </rule> 
     </rules> 
    </rewrite> 
    </system.webServer> 
+0

Dla każdego, kto znajdzie te lata później jak ja, to spowodowało błąd dla mnie w vs2017. Następująca odpowiedź podobna do tej zadziałała: https://stackoverflow.com/a/47095/4180481 – Ozan

-2

Można użyć klasy bazowej dla wszystkich kontrolerów i udekorować ją za pomocą wymaganego atrybutu ssl.

+4

Ja (lub inny członek zespołu) nie chcę przypadkowo zapomnieć o dodaniu atrybutu do nowego kontrolera, lub też zapomnieć o odziedziczeniu po klasie bazowej. Chcemy, aby był niezawodny. – CodeGrue

+0

@CodeGrue: zawsze możesz dodać test jednostki, który zapewnia, że ​​wszystkie kontrolery używają tego atrybutu; zobacz moje ostatnie pytanie dotyczące atrybutu serializowalnego: http://stackoverflow.com/questions/3257004/how-to-determine-if-all-objects-are-serializable-in-a-given-namespace – DanP

18

Zawsze możesz dodać czek na poziomie aplikacji w global.asax

protected void Application_BeginRequest(Object sender, EventArgs e) 
{ 
    if (!HttpContext.Current.Request.IsSecureConnection) 
    { 
    Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"] 
           + HttpContext.Current.Request.RawUrl); 
    } 
} 
95

Zarejestruj RequireHttpsAttribute jako filtr globalny.

W global.asax:

protected void Application_Start() 
{ 
    GlobalFilters.Filters.Add(new RequireHttpsAttribute()); 

    //... other stuff 
} 
+0

Zdecydowanie najczystsza metoda. –

+0

Robię to i otrzymuję pętlę przekierowania. Przeprojektowano URL dla mnie. –

+4

@RacielR. Miałem ten sam problem wcześniej, problemem był partner hostingowy, który zaakceptował ssl na zaporze, ale potem wysłał żądanie przez http do mojego serwera ... Upewnij się, że twój host hostingowy nie robi tego samego. – Julian

11

Wystarczy przynieść tę odpowiedź połowy dnia na MVC 3 i powyżej użyć następujących w Filterconfig.cs pliku w folderzeApp_start

 filters.Add(new RequireHttpsAttribute()); 

Oczywiście potrzebne będą twoje serwery IIS skonfigurowane do używania ważnego certyfikatu SSL, tanie certyfikaty można kupić tutaj: https://www.namecheap.com/ Myślę, że ostatni raz kupiłem jeden był 9 dolarów za domenę rocznie.

+0

Zauważ, że poświęcenie czasu na powrót i zaktualizowanie tego pytania za pomocą aktualnej odpowiedzi: –

+0

to RequireHttpsAttribute oczekuje, że przekieruje użytkowników do https, gdy użytkownicy wpiszeją http, lub spowoduje błąd 403 zamiast ? – usefulBee

+0

Co ciekawe, RequireHttpsAttribute wysyła 302 (tymczasowe) przekierowanie NIE A 301. Dziwne, ponieważ 301 jest stałym przekierowaniem, które wydaje się być bardziej stosowne tutaj. W każdym razie ważne jest, aby pamiętać, że jest to tylko pierwsze połączenie z witryną za pośrednictwem protokołu HTTP, które przesyła numer 302 do HTTPS, a wszystkie następne połączenia w tej sesji znajdują się w protokole HTTPS. Jest sposób na przezwyciężenie 302, 1 sposób sugeruje tutaj Ben http://benjii.me/2015/10/redirect-to-https-asp-net-mvc/ –

3

To nie jest użycie RequireHttps, ale myślę, że jest to lepsze rozwiązanie, ponieważ przejmuje przekierowanie wcześniej w wersji MVC Lifecycle.

public class RedirectModule : IHttpModule 
{ 
    private HttpApplication _context; 

    public void Init(HttpApplication context) 
    { 
     _context = context; 
     _context.PostResolveRequestCache += HttpRedirect; 
    } 

    public void HttpRedirect(Object src, EventArgs args) 
    { 
     if (_context.Request.Url.Scheme == Uri.UriSchemeHttp) 
     { 
      //Redirect to https 
      var scheme = Uri.UriSchemeHttps + "://"; 
      var authority = _context.Request.Url.Authority; 
      var url = _context.Request.RawUrl; 

      var redirectTo = scheme + authority + url; 
      _context.Response.PermanentRedirect(redirectTo); 
     } 
    } 

    public void Dispose() { } 
} 

Pomysł pochodził z tego article.

Możesz zarejestrować moduł w swoim Web.config lub wewnątrz Global.asax. Pokażę ci w web.cofig.

<system.webServer> 
    <modules> 
     <add name="ConfigModuleName" type="Your.Namespace.RedirectModule"/> 
    </modules> 
</system.webServer> 
+0

Myślę, że 'PermanentRedirect' powinien być' RedirectPermanent' –

+0

Wywołanie Application_BeginRequest wydaje się być wywoływane przed zdarzeniem obsługi zdarzenia zarejestrowanym w PostResolveRequestCache – odyth

0

W pliku Global.asax.cs użyj "RegisterGlobalFilters", aby zarejestrować atrybuty globalne.

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new RequireHttpsAttribute()); 
    //e.g. filters.Add(new HandleErrorAttribute()); 
    //e.g. filters.Add(new System.Web.Mvc.AuthorizeAttribute());    
} 
3

MVC 6 (ASP.NET Rdzeń 1.0) działa nieco inaczej w to sposób filtrów rejestrujących:

Startup.cs - AddMvc z filtrem dla RequireHttpsAttribute:

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

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

decyzje projektowe wyjaśnione :

  1. Użyj filtra w Startup.cs dla konfiguracji globalnej (ponieważ chcemy, aby było to wszędzie).Uruchomienie powinno być odpowiedzialne za rejestrację i konfigurację wszystkich reguł globalnych. Jeśli Twoja firma zatrudnia nowego programistę, spodziewa się znaleźć globalną konfigurację w Startup.cs.
  2. Użyj logiki RequireHttpsAttribute, ponieważ jest sprawdzona (przez Microsoft). Nigdy nie używaj "magicznych" ciągów, takich jak "http: //" i "https: //", gdy można tego uniknąć, ponownie wykorzystując składnik Microsoft stworzony w celu zapewnienia tej samej logiki.

Jeśli używasz swoją stronę MVC w localhost bez SSL:

  • http: // localhost: 1337/(bez SSL)
  • https: // localhost: 1337/(SSL)

Rozważ oglądanie how to run without SSL in localhost while still requiring https it in production.

Uwaga:

Jako alternatywnego mogliśmy zrobić „class BaseController: Kontroler” i uczynić wszystkie nasze kontrolery dziedziczą „BaseController” (zamiast kontrolera). Następnie musimy tylko ustawić globalne miejsce atrybutu 1 (i nie musimy rejestrować filtra w Startup.cs).

Niektórzy ludzie wolą styl atrybutu.

Przykład użycia:

[RequireHttpsAttribute] 
public class BaseController : Controller 
{ 
    // Maybe you have other shared controller logic.. 
} 

public class HomeController : BaseController 
{ 
    // Add endpoints (GET/POST) for Home controller 
} 
4

W swoim FilterConfig.cs zastosować to:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    // only if Debug is not enabled, do not require https for local development 
    if (!HttpContext.Current.IsDebuggingEnabled) 
      filters.Add(new RequireHttpsAttribute()); 

    //... any other filters 
} 

To powinno zmusić aplikację do korzystania https na każdej stronie.

+0

Nie widziałem jeszcze 'IsDebuggingEnabled'! – madannes

Powiązane problemy