services - ASP.NET Web API Self-Host con Autenticación de Windows
security asp net mvc (9)
Intento utilizar la opción Self-Host de ASP.NET Web API con la autenticación de Windows para poder determinar el usuario que ha iniciado sesión y finalmente aceptar o rechazar al usuario en función de su identidad. Aquí está el código de mi aplicación de consola:
using System;
using System.Web.Http;
using System.Web.Http.SelfHost;
namespace SelfHost
{
class Program
{
static void Main(string[] args)
{
var config = new HttpSelfHostConfiguration("http://myComputerName:8080");
config.UseWindowsAuthentication = true;
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
}
}
}
}
Aquí está el controlador:
[Authorize]
public class HelloController : ApiController
{
public string Get()
{
// This next line throws an null reference exception if the Authorize
// attribute is commented out.
string userName = Request.GetUserPrincipal().Identity.Name;
return "Hello " + userName;
}
}
Editar: agregué el atributo Autorizar y el depurador muestra que el código dentro del método de acción Obtener nunca se invoca. Se devuelve el siguiente HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=windows-1252" http-equiv=Content-Type></HEAD>
<BODY></BODY></HTML>
Si el atributo Autorizar está comentado, Request.GetUserPrincipal().Identity.Name
arroja una excepción de referencia nula ya que Request.GetUserPrincipal()
produce null.
¿Estás seguro de que estás pasando por la parte de autenticación? Puede usar el fiddler para verificar si las solicitudes están realmente en curso o si el servidor siempre responde con 401 no autorizado (ya que está usando la autenticación).
También podría intentar implementar su propio AuthorizeAttribute
personalizado y colocar puntos de interrupción en él para asegurarse de que sea golpeado (querrá anular el método OnAuthorization
y ver si recibe el golpe).
using System.Web.Http;
public class MyAuth : AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
base.OnAuthorization(actionContext); //put breakpoint here
}
}
Además, asegúrese de estar utilizando el atributo Authorize
de System.Web.Http
, y no de System.Web.Mvc
. Vea here por qué.
¿Has intentado poner el atributo [Authorize]
en tu controlador?
[Authorize]
public class HelloController : ApiController
Aquí hay un enlace a un video corto que explica cómo usar la autorización.
En esencia, use el atributo [Autorizar] en la clase, capture el error y devuelva una respuesta HTTP 401 y haga que el cliente la detecte y vaya a la página de inicio de sesión.
Estoy un poco tarde para esto. Sin embargo, si está utilizando Owin para autohost y necesita la autenticación de Windows. En su clase de inicio puede agregar lo siguiente.
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
}
}
He alojado "API web" en el servicio de Windows y esto es lo que hice para admitir la autenticación de Windows (básicamente basada en la pregunta anterior, las respuestas, algunos artículos relacionados, simplemente estoy consolidando, ya que puede ser útil para otros)
@HTTP Server (API web):
Set (referencia: http://msdn.microsoft.com/en-us/library/system.web.http.selfhost.httpselfhostconfiguration.clientcredentialtype(v=vs.118).aspx ),
HttpSelfHostConfiguration.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
@Cliente:
Y luego, como mencionó Allan (arriba), estableció UseDefaultCredentials en verdadero.
Usando HttpClient:
var handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
_httpClient = new HttpClient(handler);
Uso de WebClient (referencia: http://msdn.microsoft.com/en-us/library/system.net.webclient.usedefaultcredentials.aspx )
establecer el uso de webclientdefaultnatcrednetials a ''verdadero''.
¡Atentamente!
Respuesta relacionada para quién lo necesita, sobre autenticación básica con token
Combinando un poco de ayuda, información, respuestas y un sistema de autofirma que creé para una API web real, finalmente pude usar etiquetas de roles y atributos para esto. Está hecho para la etiqueta de Autorización en el encabezado.
Invocación del servidor:
var config = new HttpSelfHostConfiguration("http://localhost:8080");
config.UserNamePasswordValidator = new PHVValidator();
config.Routes.MapHttpRoute(
"API Default", "{controller}/{id}",
new { id = RouteParameter.Optional });
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new DominusForm());
}
Método de autenticación: (codificado solo por ej., Elija usuario, pase y roles desde cualquier lugar)
public class PHVValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName == "admin" && password == "123")
{
string[] rolarray = new string[] { "admin" };
IPrincipal principal = new GenericPrincipal(new GenericIdentity(userName), rolarray);
Thread.CurrentPrincipal = principal;
}
}
}
Método:
[Authorize(Roles = "admin")]
public HttpResponseMessage Get()
{
do things
}
Similar a la respuesta de pero actualizada para reflejar el uso de HTTPS. La respuesta de no funciona para HTTPS porque la llamada a base.OnConfigureBinding(httpBinding);
con HTTPS sobrescribe los cambios. Además, no puede usar httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
con HTTPS.
Use una HttpSelfHostConfiguration personalizada:
public class NtlmSelfHostConfiguration : HttpSelfHostConfiguration
{
public NtlmSelfHostConfiguration(string baseAddress)
: base(baseAddress)
{ }
public NtlmSelfHostConfiguration(Uri baseAddress)
: base(baseAddress)
{ }
protected override BindingParameterCollection OnConfigureBinding(
HttpBinding httpBinding)
{
if (this.BaseAddress.Scheme == Uri.UriSchemeHttps)
{
var ret = base.OnConfigureBinding(httpBinding);
httpBinding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Ntlm;
return ret;
}
httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
httpBinding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Ntlm;
return base.OnConfigureBinding(httpBinding);
}
}
Entonces, puedes hacer
var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");
o
var config = new NtlmSelfHostConfiguration("https://myComputerName:8443");
para obtener una configuración para pasar al new HttpSelfHostServer(config)
Solo para agregar, si está usando la solución de tpeczek y también está usando HttpClient, puede necesitar hacer esto:
var handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
_httpClient = new HttpClient(handler);
También me he topado con este problema y la única solución que he encontrado es entregar HttpSelfHostedConfiguration dedicada:
public class NtlmSelfHostConfiguration : HttpSelfHostConfiguration
{
public NtlmSelfHostConfiguration(string baseAddress)
: base(baseAddress)
{ }
public NtlmSelfHostConfiguration(Uri baseAddress)
: base(baseAddress)
{ }
protected override BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding)
{
httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
return base.OnConfigureBinding(httpBinding);
}
}
Para usarlo solo necesita cambiar una línea (ya no necesita establecer UseWindowsAuthentication):
var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");
El único problema con este enfoque es que ahora se requiere autenticación para cada solicitud realizada al servidor que utiliza esta configuración.