Windows認証でASP.NETWeb APIセルフホストオプションを使用しようとしています。これにより、ログオンしているユーザーを特定し、最終的にユーザーのIDに基づいてユーザーを承認または拒否できます。これが私のコンソールアプリケーションコードです:
_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属性を追加しましたが、デバッガーはGetactionメソッド内のコードが呼び出されないことを示しています。次の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
はnullを生成するため、Request.GetUserPrincipal()
はnull参照例外をスローします。
私もこの問題にぶつかりました。私が思いついた唯一の解決策は、専用の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);
}
}
これを使用するには、1行変更するだけです(UseWindowsAuthenticationを設定する必要はありません)。
var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");
このアプローチの唯一の問題は、この構成を使用しているサーバーに対して行われるすべての要求に対して認証が必要になることです。
私はこれに少し遅れています。ただし、Owinを使用して自己ホストし、Windows認証が必要な場合。スタートアップクラスでは、以下を追加できます。
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
}
}
私はWindowsサービスで「WebAPI」をホストしており、これはWindows認証をサポートするために行ったことです(基本的に上記の質問、回答、いくつかの関連記事に基づいています-他の人に役立つ可能性があるため、統合しています)
@ HTTPサーバー(Web API):
HttpSelfHostConfiguration.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
@ Client:
そして、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」に設定します。
宜しくお願いします!
認証部分を通過してもよろしいですか? 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
}
}
また、System.Web.Http
からではなくSystem.Web.Mvc
からのAuthorize
属性を使用していることを確認してください。 ここ 理由を参照してください。
コントローラに [Authorize]
属性を設定してみましたか?
[Authorize]
public class HelloController : ApiController
これは、認証の使用方法を説明する短いビデオへのリンクです。
http://www.asp.net/web-api/videos/getting-started/authorization
基本的に、クラスの[Authorize]属性を使用し、エラーをキャッチしてHTTP 401応答を返し、クライアントにそれを検出してログインページに移動させます。
追加するだけで、tpeczekのソリューションを使用していて、HttpClientも使用している場合は、次のことを行う必要があります。
var handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
_httpClient = new HttpClient(handler);
tpeczek の回答に似ていますが、HTTPSの使用法を反映するように更新されています。 tpeczek HTTPSを使用したbase.OnConfigureBinding(httpBinding);
の呼び出しにより変更が上書きされるため、HTTPSでは回答が機能しません。また、HTTPSで_httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
_を使用することはできません。
カスタム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)
に渡す構成を取得します
トークンを使用した基本認証について、それを必要とする人のための関連する回答
実際のWebAPI用に作成したヘルプ、情報、回答、および自己認証システムをマージすることで、最終的にこれにロールと属性タグを使用できるようになりました。ヘッダーのAuthorizationタグ用に作成されています。
サーバー呼び出し:
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
}