2012-06-29 13 views
61

C'è un modo per richiedere SSL per WebApi? Un attributo?Richiedi SSL in WebApi?

Non vedo un attributo applicabile in System.Web.Http, qualcosa come l'attributo RequireHttps che abbiamo per MVC. Sto solo cercando di evitare di far ruotare il mio gestore di attributi/messaggi se esiste una soluzione integrata.

+0

Questo è un articolo su questa domanda che vale la pena leggere: https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/working-with-ssl-in-web-api – Tohid

risposta

40

È possibile utilizzare RequireHttpsHandler dal progetto WebAPIContrib. In pratica, tutto ciò che fa è quello di verificare la richiesta in ingresso schema URI:

if (request.RequestUri.Scheme != Uri.UriSchemeHttps) 
{ 
    // Forbidden (or do a redirect)... 
} 

In alternativa, Carlos Figueira ha another implementation sul suo blog MSDN.

+1

Grazie. Ho pensato tanto, semplicemente non volevo reinventare la ruota se fosse integrata. – EBarr

47
public class RequireHttpsAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
     if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps) 
     { 
      actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden); 
     } 
    } 
} 
+10

Proprio come una FYI, la classe 'ActionFilterAttribute' che usa questo codice è in' System.Web.Http.Filters'. È ** non ** la classe 'ActionFilterAttribute' trovata in' System.Web.Mvc'. –

+4

Per quelli che si stanno chiedendo, dopo aver aggiunto questo da qualche parte, aggiungi '[RequireHttps]' sopra la tua classe/azioni. Documenti: http://www.asp.net/web-api/overview/security/working-with-ssl-in-web-api – CularBytes

+0

Io uso anche questo metodo. Ho visto molti esempi usando 'AuthorizationFilterAttribute'. Qualsiasi motivo per cui la gente usa questo oltre 'ActionFilterAttribute' ??? – Ollie

19

E 'sconcertante che non v'è alcun equivalente all'attributo ASP.NET MVC RequireHttps in ASP.NET Web API. Tuttavia puoi facilmente crearne uno basato su RequireHttps da MVC.

using System; 
using System.Net.Http; 
using System.Web.Http.Controllers; 
using System.Web.Http.Filters; 

... 

public class RequireHttpsAttribute : AuthorizationFilterAttribute 
{ 
    public override void OnAuthorization(HttpActionContext actionContext) 
    { 
     if (actionContext == null) 
     { 
      throw new ArgumentNullException("actionContext"); 
     } 

     if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps) 
     { 
      HandleNonHttpsRequest(actionContext); 
     } 
     else 
     { 
      base.OnAuthorization(actionContext); 
     } 
    } 

    protected virtual void HandleNonHttpsRequest(HttpActionContext actionContext) 
    { 
     actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden); 
     actionContext.Response.ReasonPhrase = "SSL Required"; 
    } 
} 

Tutto quello che resta da fare è discutere su quanto codice ridondante ci sia.

2

è possibile utilizzare la seguente classe di filtro per forzare il metodo di azione a utilizzare SSL, questo gestirà la richiesta con un metodo GET o qualsiasi altro verbo, se è un metodo get reindirizzerà il browser (utilizzando l'intestazione della posizione) al nuovo URI. Altrimenti verrà visualizzato un messaggio per utilizzare https

Il codice seguente indica che è necessario sovrascrivere il metodo OnAuthorization dopo aver ereditato da AuthorizationFilterAttribute.

 string _HtmlBody = string.Empty; 
     UriBuilder httpsNewUri; 

     var _Request = actionContext.Request; 

     if (_Request.RequestUri.Scheme != Uri.UriSchemeHttps) 
     { 

      _HtmlBody = "<p>Https is required</p>"; 

      if (_Request.Method.Method == "GET"){ 

       actionContext.Response = _Request.CreateResponse(HttpStatusCode.Found); 
       actionContext.Response.Content = new StringContent(_HtmlBody, Encoding.UTF8, "text/html"); 

       httpsNewUri = new UriBuilder(_Request.RequestUri); 
       httpsNewUri.Scheme = Uri.UriSchemeHttps; 
       httpsNewUri.Port = 443; 

       //To ask a web browser to load a different web page with the same URI but different scheme and port 
       actionContext.Response.Headers.Location = httpsNewUri.Uri; 


      }else{ 

       actionContext.Response = _Request.CreateResponse(HttpStatusCode.NotFound); 
       actionContext.Response.Content = new StringContent(_HtmlBody, Encoding.UTF8, "text/html"); 

      } 
} 
1

È possibile utilizzare il seguente codice; (reindirizza automaticamente a https) reindirizza a https quando viene effettuata una richiesta basata su http.

Per controllarlo in Visual Studio è necessario abilitare ssl in Visual Studio. Questo può essere fatto usando abilita la proprietà ssl su true.

public class RequireHttpsAttribute: AuthorizationFilterAttribute 
{ 
    public override void OnAuthorization(HttpActionContext actionContext) 
    { 
     if(actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps) 
     { 
      // constructing the https url 
      var uriBuilder = new UriBuilder(actionContext.Request.RequestUri) 
      { 
       Scheme = Uri.UriSchemeHttps, 
       Port = 44353 // port used in visual studio for this 
      }; 

      actionContext.Response.Headers.Location = uriBuilder.Uri; 
     } 
    } 
} 

Utilizzare questo metodo Register come questo

config.Filters.Add(new RequireHttpsAttribute()); 
0

Dopo alcune ricerche ho deciso questa è probabilmente la risposta più appropriata. Potrebbe essere aggiornato per fornire json, text o xml nonostante la specifica indicante che Html è raccomandato.

public class RequireHttpsAttribute : AuthorizationFilterAttribute 
{ 
    public override void OnAuthorization(HttpActionContext context) 
    { 
     if (context.Request.RequestUri.Scheme != Uri.UriSchemeHttps) 
     { 
      context.Response = new HttpResponseMessage(HttpStatusCode.UpgradeRequired); 
      context.Response.Headers.Add("Upgrade", "TLS/1.1, HTTP/1.1"); 
      context.Response.Headers.Add("Connection", "Upgrade"); 
      context.Response.Headers.Remove("Content-Type"); 
      context.Response.Headers.Add("Content-Type", "text/html"); 
      context.Response.Content = new StringContent("<html><head></head><body><h1>Http protocol is not valid for this service call.</h1><h3>Please use the secure protocol https.</h3></body></html>"); 
     } 
     else base.OnAuthorization(context); 
    } 
} 

Ecco le specifiche: RFC 2817