我有一个ASP.NET Web API服务,它在启用了Windows身份验证的Web服务器上运行.
我有一个基于MVC4构建的客户端站点,它运行在同一Web服务器上的不同站点上,该站点使用HttpClient从服务中提取数据.此客户端站点在启用身份模拟的情况下运行,并且还使用Windows身份验证.
Web服务器是带有IIS 7.5的Windows Server 2008 R2.
我遇到的挑战是让HttpClient通过当前的Windows用户作为其身份验证过程的一部分.我已经以这种方式配置了HttpClient:
var clientHandler = new HttpClientHandler();
clientHandler.UseDefaultCredentials = true;
clientHandler.PreAuthenticate = true;
clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
var httpClient = new HttpClient(clientHandler);
Run Code Online (Sandbox Code Playgroud)
我的理解是,在启用了身份模拟的情况下运行站点,然后以这种方式构建客户端应该导致客户端使用当前登录用户的模拟身份对服务进行身份验证.
这不会发生.事实上,客户端似乎根本没有进行身份验证.
该服务配置为使用Windows身份验证,这似乎完美.我可以在我的网络浏览器中访问http:// server/api/shippers并提示进行Windows身份验证,输入后我会收到请求的数据.
在IIS日志中,我看到收到的API请求没有进行身份验证并收到401质询响应.
关于这个的文档似乎很少.
我需要深入了解可能出现的问题或使用此应用程序使用Windows身份验证的其他方法.
谢谢,克雷格
windows-authentication iis-7.5 wcf-web-api asp.net-mvc-4 asp.net-web-api
我们碰巧运行带有API的REST Web服务,要求客户端使用基本身份验证.我们用各种语言制作了一套简洁的样本,展示了如何与我们的服务进行交互.现在我正在检查服务的IIS日志,并发现以下模式经常发生:
看起来像第一个请求没有授权标头发送,然后第二个请求与正确的标头一起发送并成功.大多数情况下,日志记录包含"user-agent",这与我们在.NET示例中植入的字符串相同.
所以我认为问题仅在于.NET程序.我们的示例代码没有重现该问题,因此我假设用户以某种方式修改了代码或从头开始编写自己的代码.
我们尝试联系用户,但显然他们不想花时间研究.所以很高兴找到导致.NET程序这种行为的最可能的情况.
他们为什么要这样做?他们为什么不在第一次尝试时附上标题?
我正在努力理解并设置一个服务和消费者,服务将在用户登录消费者时运行.
我的消费者是一个MVC应用程序.我的服务是一个Web Api应用程序.两者都在同一域内的不同服务器上运行.两者都设置为使用Windows身份验证.
我的消费者代码是:
private T GenericGet<T>(string p)
{
T result = default(T);
HttpClientHandler handler = new HttpClientHandler() { PreAuthenticate = true, UseDefaultCredentials = true };
using (HttpClient client = new HttpClient(handler))
{
client.BaseAddress = new Uri(serviceEndPoint);
HttpResponseMessage response = client.GetAsync(p).Result;
if (response.IsSuccessStatusCode)
result = response.Content.ReadAsAsync<T>().Result;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
在我的服务中,我打电话User.Identity.Name来获取来电显示,但这总是作为消费者应用程序池ID返回,而不是登录用户.消费者应用程序池作为网络服务运行,服务器本身受信任以进行委派.那么如何获取登录用户?服务代码:
// GET: /Modules/5/Permissions/
[Authorize]
public ModulePermissionsDTO Get(int ModuleID)
{
Module module= moduleRepository.Find(ModuleID);
if (module== null)
throw new HttpResponseException(HttpStatusCode.NotFound);
// This just shows as the App Pool the …Run Code Online (Sandbox Code Playgroud) 我正在尝试从.NET Core 2.0控制台应用程序进行HTTP GET调用.端点需要Windows身份验证.
我的测试程序成功实现了net45框架目标.相比之下,netcoreapp3.0构建接收401 Unauthorized.
这是我的方法:
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
static async Task<string> Get(string serverUri, string requestUri)
{
var handler = new HttpClientHandler() { UseDefaultCredentials = true };
var client = new HttpClient(handler) { BaseAddress = new Uri(serverUri) };
return await client.GetStringAsync(requestUri);
}
Run Code Online (Sandbox Code Playgroud)
这是我的项目文件.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net45;netcoreapp3.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<PackageReference Include="System.Net.Http" Version="4.3" />
</ItemGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)
运行.\bin\Debug\net45\HttpClientTest.exe返回预期的JSON结果.
跑步dotnet .\bin\Debug\netcoreapp3.0\HttpClientTest.dll收到401 Unauthorized.
Unhandled …Run Code Online (Sandbox Code Playgroud) 我有两个网站,A和B.A使用B公开的API ,并B要求Windows身份验证.两个站点都在Domain中D.
通过我的域帐户(在域中)在本地运行HttpClient站点时,API将被访问,授予访问权限.在这种情况下,实例化如下:APHttpClient
using(var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials: true }))
Run Code Online (Sandbox Code Playgroud)
当A部署到测试服务器时,上面会产生401 Unauthorized响应.测试服务器上的应用程序池在域中的服务帐户下运行D.
明确使用该服务帐户时,如下所示:
var credential = new NetworkCredential("service-account", "password", "D");
var cache = new CredentialCache
{
{
new Uri(apiServerUri), "NTLM", credential
}
};
var handler = new HttpClientHandler
{
Credentials = cache
};
using(var client = new HttpClient(handler))
...
Run Code Online (Sandbox Code Playgroud)
再次在A本地运行站点,仍然可以访问.通过浏览器直接访问API并指定服务帐户凭据时,也会授予访问权限.日志表明它绝对是用于访问API的服务帐户.
将上述部署回测试服务器仍然会导致401 …
我的Web Core API中的此代码确认我是经过身份验证的用户,但我没有获取用户名,而是获取应用程序池的名称.我该如何解决?
var testa = User.Identity.GetType();
NLogger.Info($"testa = {testa}");
var testd = User.Identity.IsAuthenticated;
NLogger.Info($"testd = {testd}");
var loggedInUser = User.Identity.Name;
NLogger.Info($"loggedInUser = {loggedInUser}");
Run Code Online (Sandbox Code Playgroud)
在我的日志文件中,我得到;
testa = System.Security.Principal.WindowsIdentity
testd = True
loggedInUser = IIS APPPOOL\SIR.WEBUI
Run Code Online (Sandbox Code Playgroud)
我使用控制器的[Authorize]标签并禁用匿名身份验证.
好吧,我从Postman调用方法,它工作正常,LoggedInUser是正确的.但是当我从我的代码中调用时,我得到了上面显示的不正确的loggedInUser.我用来从我的客户端应用程序调用web api的代码是;
public static async Task<IEnumerable<ContractDto>> GetAllForUser()
{
using (var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true }))
{
client.BaseAddress = new Uri(AppSettings.ServerPathApi);
var path = GetPath("getallforuser");
var response = await client.GetAsync(path);
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<IEnumerable<ContractDto>>(stringResult);
}
} …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
var baseUrl = "https://" + GetIdentityProviderHost(environment) + "/oauth2/authorize";
var query = $"?scope=openid&response_type=code&redirect_uri={redirectUrl}&client_id={clientId}";
var combinedUrl = baseUrl + query;
var currentUser = WindowsIdentity.GetCurrent();
await WindowsIdentity.RunImpersonated(currentUser.AccessToken, async() =>
{
using (var client = new WebClient{ UseDefaultCredentials = true })
{
var response = client.DownloadString(combinedUrl);
Console.WriteLine(response);
}
});
Run Code Online (Sandbox Code Playgroud)
它基本上构造一个 URL,然后调用它。
调用返回 401(未授权)。
但是,如果我将其combinedUrl粘贴到 chrome 或 postman 中,它就可以完美运行。这告诉我我的通话可以正常工作,因为 Chrome 正在使用我的 Windows 凭据进行通话。
我添加了WindowsIdentity.RunImpersonated代码来尝试解决这个问题。但是好像没有什么效果。
如何使用集成 Windows 身份验证 (IWA) 进行网络呼叫?
细节:
如果我运行以下 cURL 命令,它会起作用:
curl -L --negotiate -u : …Run Code Online (Sandbox Code Playgroud) 这似乎是一个很遥远的事情。但我看到几个答案表明,当 .Net Core 应用程序中需要 cURL 时,应该使用 HttpClient (和类似的)。
我有以下 cURL 命令(完美运行):
curl -v -L --negotiate -u : -b ~/cookiejar.txt "https://idp.domain.net/oauth2/authorize?scope=openid&response_type=code&redirect_uri=https://localhost:5001&client_id=client_id_here"
Run Code Online (Sandbox Code Playgroud)
该命令的流程如下:
-L选项在那里,所以它遵循重定向www-authenticate:Negotiate标头的 401(未经授权)。www-authenticate:Negotiate标头并从操作系统获取 Kerberos 令牌(因为--negotiate和-u选项)。Authorization: Negotiate <kerberos token here>.-b选项,cURL 会拾取 cookie。更新 原来我需要做的就是升级到 .NET Core 2.1!谢谢大家的解答!
我有一个 .NET Core 2.0 控制台应用程序,需要向使用 Windows 身份验证(特别是 NTLM)的 API 发出 Web 请求。这是我公司的内部 API,我很难成功连接到它,不断收到 401。
我的研究
我检查了SO:
然后我发现了在 .NET Core github 中提出的这个问题,它说它已经解决了。我尝试按照那里的代码示例进行操作,但仍然无效。
我的代码
这是我到目前为止所做的,我更改了 Uri,因为它托管在公司网络上,但我希望这足以在本地运行。
public class NTLMProxy
{
private readonly HttpClient _httpClient;
public NTLMProxy()
{
_httpClient = …Run Code Online (Sandbox Code Playgroud) 我将 .NET 应用程序从版本 NET5 升级到 NET6,并发出警告,指出 WebRequest 类已过时。我在网上查看了一些示例,但是使用 HttpClient 不会像 WebRequest 那样自动获取凭据,因为您需要手动将它们插入到字符串中。
我如何使用 HttpClient 类或类似的类来转换它?
string url = "website.com";
WebRequest wr = WebRequest.Create(url);
wr.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse hwr = (HttpWebResponse)wr.GetResponse();
StreamReader sr = new(hwr.GetResponseStream());
sr.Close();
hwr.Close();
Run Code Online (Sandbox Code Playgroud) c# ×7
.net-core ×4
.net ×2
asp.net ×1
asp.net-mvc ×1
curl ×1
http ×1
httpclient ×1
iis ×1
iis-7.5 ×1
ntlm ×1
wcf-web-api ×1
web-services ×1
webrequest ×1