HttpClient调用Windows-Authenication ApiController方法…但没有WindowsIdentity出现
当api-controller使用windows-authentication时,我的api控制器是否有办法获得启动api控制器调用的帐户的IIdentity?
我的“castController.User.Identity”是(类型)WindowsIdentity。 但它是“空的”。 空,原样:IsAuthenticated = false,以及一个空的UserName。 它不是空的,它是“空的”。
我的“WebTier”是一个运行自定义AppPool的IIS应用程序,运行自定义AppPool的IIdentity类似于“mydomain myServiceAccount”。 我正在尝试将“castController.User.Identity.Name”值作为此服务帐户。
(我想这可能是任何能够使用有效的Windows帐户连接到我的WebApiTier的客户端,但我提到这个以防万一它可能会抛出一个奇怪的猴子扳手)
我的“WebTier”(Mvc Application)有这样的方法:
你会注意到我使用UseDefaultCredentials的两种方法。 (阿卡,我一直试图解决这个问题)
private async Task ExecuteProxy(string url) { HttpClientHandler handler = new HttpClientHandler() { UseDefaultCredentials = true }; handler.PreAuthenticate = true; WebRequestHandler webRequestHandler = new WebRequestHandler(); webRequestHandler.UseDefaultCredentials = true; webRequestHandler.AllowPipelining = true; webRequestHandler.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequired; webRequestHandler.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification; using (var client = new HttpClient(handler)) /* i've tried webRequestHandler too */ { Uri destinationUri = new Uri("https://localhost/MyVirtualDirectory/api/mycontroller/mymethod"); this.Request.RequestUri = destinationUri; return await client.SendAsync(this.Request); } }
“WebApiTier”安装程序。
web.config中
“WebApiTier”代码
public MyController : ApiController { [ActionName("MyMethod")] [MyCustomAuthorization] public IEnumerable MyMethod() { return new string[] { "value1", "value2" }; } } public class MyCustomAuthorizationAttribute : System.Web.Http.AuthorizeAttribute { private string CurrentActionName { get; set; } public override void OnAuthorization(HttpActionContext actionContext) { this.CurrentActionName = actionContext.ActionDescriptor.ActionName; base.OnAuthorization(actionContext); } protected override bool IsAuthorized(HttpActionContext actionContext) { var test1 = System.Threading.Thread.CurrentPrincipal; /* the above is "empty" */ ////string userName = actionContext.RequestContext.Principal;/* Web API v2 */ string userName = string.Empty; ApiController castController = actionContext.ControllerContext.Controller as ApiController; if (null != castController) { userName = castController.User.Identity.Name; /* the above is "empty" */ } return true; } }
}
再次。 我不是在做“双跳”(我在几个地方读过)。
两个层都在同一个域(和本地开发,它们在同一台机器上)….
有趣的是,我已经读过这篇文章( 如何让HttpClient与请求一起传递凭据? )并且“问题”报告确实是我希望我的工作方式。 (?!?!)。
对于开发,“WebApiTier”在完整的IIS下运行。 对于“WebTier”,我在IIS-Express和全functionIIS下尝试过。
我还使用以下代码运行了一个控制台应用程序:
控制台应用
IEnumerable returnItems = null; HttpClientHandler handler = new HttpClientHandler() { UseDefaultCredentials = true }; handler.PreAuthenticate = true; WebRequestHandler webRequestHandler = new WebRequestHandler(); webRequestHandler.UseDefaultCredentials = true; webRequestHandler.AllowPipelining = true; webRequestHandler.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequired; webRequestHandler.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification; HttpClient client = new HttpClient(handler); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); string serviceUrl = "https://localhost/MyVirtualDirectory/api/mycontroller/mymethod"; HttpResponseMessage response = client.GetAsync(new Uri(serviceUrl)).Result; var temp1 = (response.ToString()); var temp2 = (response.Content.ReadAsStringAsync().Result); if (response.IsSuccessStatusCode) { Task<IEnumerable> wrap = response.Content.ReadAsAsync<IEnumerable>(); if (null != wrap) { returnItems = wrap.Result; } else { throw new ArgumentNullException("Task<IEnumerable>.Result was null. This was not expected."); } } else { throw new HttpRequestException(response.ReasonPhrase + " " + response.RequestMessage); }
与其他代码的结果相同。 一个“空”的Windows身份。
我也经历了这个
https://www.iis.net/configreference/system.webserver/security/authentication/windowsauthentication
就像一个健全检查。
好。 我想出了这个问题。 感谢这篇文章。
如何在asp.net中识别impersonate =“true”时获取Windows用户名?
//开始引用//
使用应用程序中的
并在IIS中启用匿名访问,您将看到以下结果:
System.Environment.UserName: Computer Name Page.User.Identity.Name: Blank System.Security.Principal.WindowsIdentity.GetCurrent().Name: Computer Name
//结束报价
因此,我还将包括一个完整的答案…….以显示问题和一些可能需要调整的设置。
去下载这个迷你示例。
https://code.msdn.microsoft.com/ASP-NET-Web-API-Tutorial-8d2588b1
这将为您提供一个名为ProductsApp(ProductsApp.csproj)的快速“WebApiTier”。
如果你想自己做….只需创建一个WebApi控制器……返回一些产品。
public class ProductsController : ApiController { Product[] products = new Product[] { new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } }; [IdentityWhiteListAuthorization] public IEnumerable GetAllProducts() { return products; } }
打开上面的.sln。
添加一个名为“WebApiIdentityPoc.Domain.csproj”的新“类库”csproj。
在此库中创建一个新类。
namespace WebApiIdentityPoc.Domain { public class Product { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } }
删除(或注释掉)
ProductsApp 型号 Product.cs
将ProductsApp中的(项目)引用添加到WebApiIdentityPoc.Domain。
修复名称空间问题
ProductsApp 控制器ProductsController.cs
//using ProductsApp.Models; using WebApiIdentityPoc.Domain; namespace ProductsApp.Controllers { public class ProductsController : ApiController {
(您基本上将“Product”对象移动到另一个库,以便Server和Client可以共享同一个对象。)
你应该能够在这一点上进行编译。
……….
向解决方案添加新的“控制台应用程序”项目。
WebApiIdentityPoc.ConsoleOne.csproj
使用Nuget将“Newtonsoft.Json”引用/库添加到WebApiIdentityPoc.ConsoleOne.csproj。
使用右键单击/添加引用在csproj中的“/ References”文件夹中添加引用(Framework或Extensions)
System.Net.Http System.Net.Http.Formatting System.Net.Http.WebRequest (this one is may not be needed)
添加项目引用到WebApiIdentityPoc.Domain。
在控制台应用程序的“Program.cs”中,粘贴此代码:………….
namespace WebApiIdentityPoc.ConsoleOne { using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Security.Principal; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using WebApiIdentityPoc.Domain; public class Program { private static readonly string WebApiExampleUrl = "https://localhost:47503/api/Products/GetAllProducts"; /* check ProductsApp.csproj properties, "Web" tab, "IIS Express" settings if there is an issue */ public static void Main(string[] args) { try { System.Security.Principal.WindowsIdentity ident = System.Security.Principal.WindowsIdentity.GetCurrent(); if (null != ident) { Console.WriteLine("Will the Identity '{0}' Show up in IdentityWhiteListAuthorizationAttribute ???", ident.Name); } RunHttpClientExample(); RunWebClientExample(); RunWebClientWicExample(); } catch (Exception ex) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); Exception exc = ex; while (null != exc) { sb.Append(exc.GetType().Name + System.Environment.NewLine); sb.Append(exc.Message + System.Environment.NewLine); exc = exc.InnerException; } Console.WriteLine(sb.ToString()); } Console.WriteLine("Press ENTER to exit"); Console.ReadLine(); } private static void RunWebClientExample() { /* some articles said that HttpClient could not pass over the credentials because of async operations, these were some "experiments" using the older WebClient. Stick with HttpClient if you can */ WebClient webClient = new WebClient(); webClient.UseDefaultCredentials = true; string serviceUrl = WebApiExampleUrl; string json = webClient.DownloadString(serviceUrl); IEnumerable returnItems = JsonConvert.DeserializeObject>(json); ShowProducts(returnItems); } private static void RunWebClientWicExample() { /* some articles said that HttpClient could not pass over the credentials because of async operations, these were some "experiments" using the older WebClient. Stick with HttpClient if you can */ System.Security.Principal.WindowsIdentity ident = System.Security.Principal.WindowsIdentity.GetCurrent(); WindowsImpersonationContext wic = ident.Impersonate(); try { WebClient webClient = new WebClient(); webClient.UseDefaultCredentials = true; string serviceUrl = WebApiExampleUrl; string json = webClient.DownloadString(serviceUrl); IEnumerable returnItems = JsonConvert.DeserializeObject>(json); ShowProducts(returnItems); } finally { wic.Undo(); } } private static void RunHttpClientExample() { IEnumerable returnItems = null; HttpClientHandler handler = new HttpClientHandler() { UseDefaultCredentials = true, PreAuthenticate = true }; ////////WebRequestHandler webRequestHandler = new WebRequestHandler(); ////////webRequestHandler.UseDefaultCredentials = true; ////////webRequestHandler.AllowPipelining = true; ////////webRequestHandler.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequired; ////////webRequestHandler.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification; using (HttpClient client = new HttpClient(handler)) { client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); string serviceUrl = WebApiExampleUrl; HttpResponseMessage response = client.GetAsync(new Uri(serviceUrl)).Result; var temp1 = response.ToString(); var temp2 = response.Content.ReadAsStringAsync().Result; if (response.IsSuccessStatusCode) { Task> wrap = response.Content.ReadAsAsync>(); if (null != wrap) { returnItems = wrap.Result; } else { throw new ArgumentNullException("Task>.Result was null. This was not expected."); } } else { throw new HttpRequestException(response.ReasonPhrase + " " + response.RequestMessage); } } ShowProducts(returnItems); } private static void ShowProducts(IEnumerable prods) { if (null != prods) { foreach (Product p in prods) { Console.WriteLine("{0}, {1}, {2}, {3}", p.Id, p.Name, p.Price, p.Category); } Console.WriteLine(string.Empty); } } } }
您应该能够编译并运行并在控制台应用程序中看到一些产品显示。
…..
在“ProductsApp.csproj”中,添加一个新文件夹。
/ WebApiExtensions /
在此文件夹下,添加一个新文件:
IdentityWhiteListAuthorizationAttribute.cs
粘贴此代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Http.Controllers; namespace ProductsApp.WebApiExtensions { public class IdentityWhiteListAuthorizationAttribute : System.Web.Http.AuthorizeAttribute { public IdentityWhiteListAuthorizationAttribute() { } private string CurrentActionName { get; set; } public override void OnAuthorization(HttpActionContext actionContext) { this.CurrentActionName = actionContext.ActionDescriptor.ActionName; base.OnAuthorization(actionContext); } protected override bool IsAuthorized(HttpActionContext actionContext) { var test1 = System.Threading.Thread.CurrentPrincipal; var test2 = System.Security.Principal.WindowsIdentity.GetCurrent(); ////string userName = actionContext.RequestContext.Principal.Name;/* Web API v2 */ string dingDingDingUserName = string.Empty; ApiController castController = actionContext.ControllerContext.Controller as ApiController; if (null != castController) { dingDingDingUserName = castController.User.Identity.Name; } string status = string.Empty; if (string.IsNullOrEmpty(dingDingDingUserName)) { status = "Not Good. No dingDingDingUserName"; } else { status = "Finally!"; } return true; } } }
使用此属性装饰webapimethod。
[IdentityWhiteListAuthorization] public IEnumerable GetAllProducts() { return products; }
(您必须解析命名空间)。
此时,您应该能够编译….并运行。
但是dingDingDingUserName将是string.Empty。 (跨越这篇文章的原始问题)。
好..
在解决方案资源管理器中单击(左键单击一次)ProductsApp.csproj。
查看属性选项卡。 (这不是“右键单击/属性:::当您只需左键单击ProductsApp.csproj时,这是显示的属性(默认位于VS的右下角)。
你会看到几个设置,但有两个有趣:
Anonymous Authentication | Enabled Windows Authentication | Enabled
(注意,以上是这些设置在VS GUI中的显示方式。它们在.csproj文件中显示如下)
enabled enabled
如果你设置
Anonymous Authentication | Disabled
(在.csproj中显示如下:
disabled enabled
)
瞧! 应显示“dingDingDingName”值。
我上面的链接..指向匿名认证 – 启用问题。
但是这里有一个很长的例子来展示关于HttpClient的直接影响……
我一路上学到了一个警告。
如果你不能改变
Anonymous Authentication Enabled/Disabled Windows Authentication Enabled/Disabled
设置,然后您需要调整“主设置”。
在IIS Express中,这将位于如下文件中:
C:用户 MyUserName输入文档 IISExpress 设置对ApplicationHost.config
“主设置”需要允许覆盖本地设置。
身份validation本身需要在主级别打开。
(完整的IIS将具有类似的设置
C: WINDOWS SYSTEM32 INETSRV 设置的applicationHost.config
)
底线:
HttpClient可以通过运行HttpClient代码的进程的WindowsIdentity发送….使用HttpClientHandler AND如果为WindowsAuthentication设置了WebApiTier并且关闭了匿名身份validation。
好。 我希望将来帮助某人。
上述就是C#学习教程:HttpClient调用Windows-Authenication ApiController方法…但没有WindowsIdentity出现分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1011398.html