24

我正在尝试将 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;
    }
}

编辑 - 我添加了 Authorize 属性,调试器显示 Get 操作方法中的代码从未被调用。返回以下 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()产生空值。

4

9 回答 9

25

我也遇到了这个问题,我想出的唯一解决方案是提供专用的 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");

这种方法的唯一问题是,现在对使用此配置的服务器发出的每个请求都需要进行身份验证。

于 2012-03-25T21:46:14.153 回答
3

我在 Windows 服务中托管了“Web API”,这就是我为支持 Windows 身份验证所做的(基本上基于上述问题、答案、一些相关文章——我只是在巩固,因为它可能对其他人有帮助)

@HTTP 服务器(网络 API):

设置(参考: http: //msdn.microsoft.com/en-us/library/system.web.http.selfhost.httpselfhostconfiguration.clientcredentialtype (v=vs.118).aspx ),

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

@客户:

然后正如 Allan 提到的(上面)将 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

将 webclient 的 usedefaultcrednetials 设置为“true”。

最好的祝福!

于 2014-05-22T19:12:46.843 回答
3

我对此有点晚了。但是,如果您使用 Owin 进行自我托管并需要 Windows 身份验证。在您的启动课程中,您可以添加以下内容。

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
        listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
    }
}
于 2016-04-26T16:49:36.833 回答
2

您确定您正在通过身份验证部分吗?您可以使用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
    }
}

另外,请确保您使用的是Authorizefrom 属性System.Web.Http,而不是 from System.Web.Mvc。看看这里为什么。

于 2012-03-23T08:24:36.380 回答
2

类似于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)

于 2014-12-12T23:53:59.573 回答
1

您是否尝试过将[Authorize]属性放在控制器上?

[Authorize]
public class HelloController : ApiController
于 2012-03-05T20:51:43.937 回答
1

这是一个简短视频的链接,该视频解释了如何使用授权。

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

本质上使用类上的 [Authorize] 属性,捕获错误并返回 HTTP 401 响应,然后让客户端检测到它并转到登录页面

于 2012-03-07T05:35:55.170 回答
1

补充一点,如果您使用 tpeczek 的解决方案并且还使用 HttpClient,您可能需要这样做:

        var handler = new HttpClientHandler();
        handler.UseDefaultCredentials = true;
        _httpClient = new HttpClient(handler);
于 2013-10-16T19:49:27.220 回答
0

谁需要它的相关答案,关于带有令牌的基本身份验证

合并我为真正的 Web 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
}
于 2017-07-25T17:51:19.733 回答