2012-06-29 13 views
61

¿Hay alguna manera de requerir SSL para WebApi? Un atributo?¿Requiere SSL en WebApi?

No veo un atributo aplicable bajo System.Web.Http, algo así como el atributo RequireHttps que tenemos para MVC. Estoy tratando de evitar rodar mi propio controlador de atributo/mensaje si hay una solución integrada.

+0

Este es un artículo sobre esta cuestión que vale la pena leer: https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/working-with-ssl-in-web-api – Tohid

Respuesta

40

Puede usar el RequireHttpsHandler del proyecto WebAPIContrib. Básicamente, lo único que hace es comprobar la solicitud entrante URI esquema:

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

Alternativamente, Carlos Figueira another implementation en su blog de MSDN.

+1

Gracias. Pensé que no quería reinventar la rueda si estaba incorporada. – 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

Al igual que un FYI, la clase 'ActionFilterAttribute' que utiliza este código está en' System.Web.Http.Filters'. Es ** no ** la clase 'ActionFilterAttribute' que se encuentra en' System.Web.Mvc'. –

+4

Para aquellos que se preguntan, después de agregar esto en alguna parte, agregue '[RequireHttps]' sobre su clase/acciones. Documentos: http://www.asp.net/web-api/overview/security/working-with-ssl-in-web-api – CularBytes

+0

Uso este método también. He visto muchos ejemplos usando 'AuthorizationFilterAttribute'. ¿Alguna razón por la cual las personas usan esto en lugar de 'ActionFilterAttribute'? – Ollie

19

Es desconcertante que no haya un equivalente al atributo ASP.NET MVC RequireHttps en ASP.NET Web API. Sin embargo, puede crear fácilmente uno basado en RequireHttps de 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"; 
    } 
} 

Todo lo que queda por hacer es discutir cuánto código redundante hay.

2

Puede usar la siguiente clase de filtro para forzar su método de acción para usar SSL, esto manejará su solicitud ya sea un método GET o cualquier otro verbo, si es un método get redirigirá el navegador (usando el encabezado de ubicación) al nuevo URI. De lo contrario, se mostrará un mensaje para usar https

El siguiente código muestra que debe anular el método de Autorización después de heredar de 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

Puede usar el siguiente código; (redirigir automáticamente a https) redirigir a https cuando se realiza una solicitud basada en http.

Para comprobarlo en el estudio visual debe habilitar ssl en visual studio. Esto puede hacerse utilizando la propiedad enable ssl en 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; 
     } 
    } 
} 

utilizar esto en el registro de método como este

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

Después de algunas investigaciones determiné esta es probablemente la respuesta más apropiada. Se podría actualizar para proporcionar json, text o xml, a pesar de que se recomienda especificar Html.

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); 
    } 
} 

Aquí es la especificación: RFC 2817