ASP.NET Web API Self-Host с аутентификацией Windows - PullRequest
23 голосов
/ 05 марта 2012

Я пытаюсь использовать параметр ASP.NET Web API Self-Host с аутентификацией Windows, чтобы я мог определить пользователя, вошедшего в систему, и в конечном итоге принять или отклонить пользователя на основе его личности. Вот мой код консольного приложения:

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

Вот контроллер:

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

Edit - я добавил атрибут Authorize, и отладчик показывает, что код внутри метода Get action никогда не вызывается. Возвращается следующий 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>

Если атрибут Authorize закомментирован, Request.GetUserPrincipal().Identity.Name выдает исключение нулевой ссылки, поскольку Request.GetUserPrincipal() возвращает ноль.

Ответы [ 9 ]

23 голосов
/ 26 марта 2012

Я тоже столкнулся с этой проблемой, и единственное решение, которое я нашел, - это предоставить выделенную конфигурацию HttpSelfHostedConfiguration:

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

Чтобы использовать ее, вам просто нужно изменить одну строку (вы небольше не нужно устанавливать UseWindowsAuthentication):

var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");

Единственная проблема с этим подходом состоит в том, что аутентификация теперь требуется для каждого запроса к серверу, который использует эту конфигурацию.

3 голосов
/ 26 апреля 2016

Я немного опоздал на это.Однако, если вы используете Owin для самостоятельного размещения и нуждаетесь в аутентификации Windows.В своем классе запуска вы можете добавить следующее.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
        listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
    }
}
3 голосов
/ 22 мая 2014

Я разместил «Web API» в службе Windows, и это то, что я сделал для поддержки проверки подлинности Windows (в основном на основе вышеупомянутого вопроса, ответов, некоторых связанных статей - я просто объединяюсь, поскольку это может быть полезно для других)

@ HTTP-сервер (веб-интерфейс):

Set (ссылка: http://msdn.microsoft.com/en-us/library/system.web.http.selfhost.httpselfhostconfiguration.clientcredentialtype(v=vs.118).aspx),

HttpSelfHostConfiguration.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;

@ Клиент:

И затем, как упоминал Аллан (см. Выше), установите для UseDefaultCredentials значение true.

Используя HttpClient:

var handler = new HttpClientHandler();
    handler.UseDefaultCredentials = true;
    _httpClient = new HttpClient(handler);

Используя WebClient (ссылка: http://msdn.microsoft.com/en-us/library/system.net.webclient.usedefaultcredentials.aspx)

установить для usedefaultcrednetials пользователя webclient значение true.

С наилучшими пожеланиями!

2 голосов
/ 23 марта 2012

Вы уверены, что проходите через аутентификацию? Вы можете использовать fiddler , чтобы проверить, действительно ли запросы выполняются или сервер всегда отвечает 401 Unauthorized (так как вы используете аутентификацию).

Вы также можете попытаться реализовать свой собственный AuthorizeAttribute и поместить в него точки останова, чтобы убедиться, что он попадет (вам нужно переопределить метод OnAuthorization и посмотреть, ударит ли он).

using System.Web.Http;
public class MyAuth : AuthorizeAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        base.OnAuthorization(actionContext); //put breakpoint here
    }
}

Также убедитесь, что вы используете атрибут Authorize из System.Web.Http, а не из System.Web.Mvc. Смотри здесь почему.

1 голос
/ 13 декабря 2014

Аналогичен ответу tpeczek , но обновлен с учетом использования HTTPS.Ответ tpeczek не работает для HTTPS, потому что вызов base.OnConfigureBinding(httpBinding); с HTTPS перезаписывает изменения.Кроме того, вы не можете использовать httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly; с HTTPS.

Использовать пользовательскую конфигурацию HttpSelfHostConfiguration:

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

Затем вы можете сделать

var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");

или

var config = new NtlmSelfHostConfiguration("https://myComputerName:8443");

чтобы получить конфигурацию для передачи в new HttpSelfHostServer(config)

1 голос
/ 16 октября 2013

Просто добавьте, что если вы используете решение tpeczek и также используете HttpClient, вам может потребоваться сделать следующее:

        var handler = new HttpClientHandler();
        handler.UseDefaultCredentials = true;
        _httpClient = new HttpClient(handler);
1 голос
/ 07 марта 2012

Вот ссылка на короткое видео, объясняющее, как использовать авторизацию.

http://www.asp.net/web-api/videos/getting-started/authorization

По сути, используйте атрибут [Authorize] класса, перехватите ошибку и верните ответ HTTP 401, а затем попросите клиента обнаружить его и перейти на страницу входа

1 голос
/ 06 марта 2012

Вы пытались добавить атрибут [Authorize] на свой контроллер?

[Authorize]
public class HelloController : ApiController
0 голосов
/ 25 июля 2017

Соответствующий ответ, для которого он нужен, об базовой аутентификации с токеном

Объединение некоторой справки, информации, ответов и системы самоутверждения, которую я создал для реального веб-API, мог бы наконец использовать теги ролей и атрибутов дляэтот.Создан для тега авторизации в заголовке.

Вызов сервера:

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

Метод аутентификации: (жестко запрограммирован только для выбора, выберитепользователь, пароль и роли из любого места)

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

Метод:

[Authorize(Roles = "admin")]
public HttpResponseMessage Get()
{
     do things
}
...