ASP.NET Auto-hôte de L'API Web avec authentification Windows
j'essaie d'utiliser le ASP.NET Option Libre-hôte de L'API Web avec authentification Windows pour que je puisse déterminer l'utilisateur connecté et finalement accepter ou rejeter l'utilisateur en fonction de leur identité. Voici le code d'application de ma console:
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();
}
}
}
}
voici le contrôleur:
[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-j'ai ajouté L'attribut Authorize, et le débogueur montre que le code à l'intérieur de la méthode Get action n'est jamais invoqué. Le HTML suivant est retourné:
<!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 L'attribut Authorize est commenté, Request.GetUserPrincipal().Identity.Name
jette une exception de référence nulle puisque Request.GetUserPrincipal()
produit nul.
9 réponses
j'ai également abordé ce problème et la seule solution que j'ai trouvée est de fournir une configuration dédiée à Httpselfhosted:
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);
}
}
pour l'utiliser, vous avez juste besoin de changer une ligne (vous n'avez plus besoin de définir UseWindowsAuthentication):
var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");
le seul problème avec cette approche est que l'authentification est maintenant nécessaire pour chaque requête faite au serveur qui utilise cette configuration.
j'ai hébergé "Web API" dans le service windows et c'est ce que j'ai fait pour prendre en charge l'authentification windows (essentiellement basé sur la question ci - dessus, les réponses, certains articles connexes-Je ne fais que consolider car il peut être utile pour d'autres)
@serveur HTTP (api web):
Ensemble (la référence: http://msdn.microsoft.com/en-us/library/system.web.http.selfhost.httpselfhostconfiguration.clientcredentialtype(v=vs. 118).aspx ),
HttpSelfHostConfiguration.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
@Client:
et puis, comme Allan l'a mentionné (ci-dessus), a placé UseDefaultCredentials à true.
Utilisant HttpClient:
var handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
_httpClient = new HttpClient(handler);
utilisant WebClient (référence: http://msdn.microsoft.com/en-us/library/system.net.webclient.usedefaultcredentials.aspx )
place webclient's usedefaultcrednetials à 'true'.
Meilleures Salutations!
je suis un peu en retard. Cependant, si vous utilisez Owin pour vous auto-héberger et que vous avez besoin de windows auth. Dans votre classe de démarrage, vous pouvez ajouter ce qui suit.
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
}
}
êtes-vous sûr de passer la partie authentification? Vous pouvez utiliser fiddler pour vérifier si les requêtes passent réellement ou si le serveur répond toujours avec 401 non autorisé (puisque vous utilisez l'authentification).
vous pouvez également essayer de mettre en œuvre votre propre coutume AuthorizeAttribute
et y mettre des points d'arrêt pour s'assurer qu'il est frappé (vous voudrez outrepasser la méthode OnAuthorization
et voir si cela est frappé).
using System.Web.Http;
public class MyAuth : AuthorizeAttribute
{
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
base.OnAuthorization(actionContext); //put breakpoint here
}
}
en outre, assurez-vous que vous utilisez l'attribut Authorize
de System.Web.Http
, et non de System.Web.Mvc
. Voir ici pourquoi.
avez-vous essayé de mettre l'attribut [Authorize]
sur votre contrôleur?
[Authorize]
public class HelloController : ApiController
Voici un lien vers une courte vidéo expliquant comment utiliser l'autorisation.
http://www.asp.net/web-api/videos/getting-started/authorization
utilisez essentiellement l'attribut [Authorize] sur la classe, saisissez l'erreur et renvoyez une réponse HTTP 401, puis demandez au client de la détecter et allez à la page de connexion
juste pour ajouter, si vous utilisez la solution de tpeczek et aussi HttpClient, vous pourriez avoir besoin de faire ceci:
var handler = new HttpClientHandler();
handler.UseDefaultCredentials = true;
_httpClient = new HttpClient(handler);
similaire à tpeczek 'S réponse mais mis à jour pour refléter L'usage HTTPS. tpeczek 's réponse ne fonctionne pas pour HTTPS parce que l'appel à base.OnConfigureBinding(httpBinding);
avec HTTPS écrase les modifications. De plus, vous ne pouvez pas utiliser httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
avec HTTPS.
utiliser une personnalisation 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);
}
}
Ensuite, vous pouvez faire
var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");
ou
var config = new NtlmSelfHostConfiguration("https://myComputerName:8443");
pour obtenir une configuration pour passer dans new HttpSelfHostServer(config)
réponse liée pour qui en a besoin, à propos de l'auth de base avec token
fusionnant de l'aide, de l'information, des réponses et un auth system que j'ai créé pour une vraie API Web, je pourrais enfin utiliser des balises de rôles et d'attributs pour cela. Est fait pour L'étiquette D'autorisation dans l'en-tête.
invocation du serveur:
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());
}
Auth Méthode: (codé en dur pour les anciens. seulement, choisissez utilisateur, passe et rôles de n'importe où)
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éthode:
[Authorize(Roles = "admin")]
public HttpResponseMessage Get()
{
do things
}