从以前的帖子更新。我已经让它工作了,我当前的设置不是我期望产生的结果。我在 Win 2012 R2 上使用 IIS 8.5
- AppPool:设置为集成管道
- AppPool:加载用户配置文件:False
- AppPool:在为委派配置的域服务帐户下运行的 IIS
- 在应用程序 > 身份验证中。ASP.Net 模拟:已禁用。Windows 身份验证:启用 w/kernel mode off。提供者:协商:Keberos。
- 配置编辑器 > system.webServer/security/authentication/windowsAuthentication useAppPoolCredentials: True。使用内核模式:假
- 本地安全策略 > 本地策略 > 用户权限分配:服务帐户必须在策略“身份验证后模拟客户端”中列出的组中
修改 Aspnet.config (C:\Windows\Microsoft.NET\Framework64\v4.0.30319)
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="false" />
<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>
<SymbolReadingPolicy enabled="1" />
<shadowCopyVerifyByTimestamp enabled="true"/>
</runtime>
<startup useLegacyV2RuntimeActivationPolicy="true" />
</configuration>
以下是正在运行的服务源。我留下了所有注释掉的代码,这样你就可以看到我一直在尝试的所有内容。请注意,只需要一些活动代码。
//using(HostingEnvironment.Impersonate())
//{
try
{
//DC = new PrincipalContext(ContextType.Domain, myDomain);
//GP = GroupPrincipal.FindByIdentity(DC, IdentityType.Name, Constant.QMS_GROUP_PRINCIPAL);
//ImpersonationContext = ((System.Security.Principal.WindowsIdentity)System.Threading.Thread.CurrentPrincipal.Identity).Impersonate();
//the service creation gets called regularly and
//autodiscovery is very slow
if(PerformanceHelper.GetMailService() != null)
{
return PerformanceHelper.GetMailService();
}
//create a service
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
service.TraceListener = new TraceListener();
service.TraceEnabled = true;
service.TraceFlags = TraceFlags.All;
service.CookieContainer = new CookieContainer(1);
service.PreAuthenticate = true;
//CredentialCache credCache = new CredentialCache();
//credCache.Add(new Uri(Constant.QMS_EXCHANGE_SVC), "Negotiate",
// CredentialCache.DefaultNetworkCredentials);
//HttpWebRequest req = (HttpWebRequest)WebRequest.Create(new Uri(Constant.QMS_EXCHANGE_SVC));
//req.Credentials = credCache;
//service.Credentials = credCache.GetCredential(new Uri(Constant.QMS_EXCHANGE_SVC), "Negotiate");
NetworkCredential nc = new NetworkCredential();
nc = CredentialCache.DefaultNetworkCredentials;
//nc = (NetworkCredential)CredentialCache.DefaultCredentials;
service.Credentials = nc;
ErrorHelper.AddErrorMsg("makeExchangeConnection IsWindowsIdentityFlowSuppressed() (info): "
+ Convert.ToString(System.Security.SecurityContext.IsWindowsIdentityFlowSuppressed()));
//WebCredentials wc = new WebCredentials(System.Net.CredentialCache.DefaultCredentials);
//WebCredentials wc = new WebCredentials(System.Net.CredentialCache.DefaultCredentials);
//service.Credentials = wc;
ErrorHelper.AddErrorMsg("makeExchangeConnection (info): " + System.Threading.Thread.CurrentPrincipal.Identity.Name);
//use the windows login credential
service.UseDefaultCredentials = true;
//the autodiscovery has been failing in dev.
//the catch should rescue the connetcion.
//I'm disabling this for now and just
//declaring the service via constant. The failing
//auto discover is a big performance hit
//especially since it can't work behind the
//firewall
//try
//{
// service.AutodiscoverUrl(eMailAddress, redirectionUrlValidationCallback);
//}
//catch
//{
// service.Url = new Uri(Constant.QMS_EXCHANGE_SVC);
//}
service.Url = new Uri(Constant.QMS_EXCHANGE_SVC);
/* 01/6/2017 Enable below to allow for impersonation on
* on the exchange server. This is pending an exchange
* adminstrator granting access for the service accounts.
*/
//if(ui.Email != null)
// service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, ui.Email);
//cache the service
PerformanceHelper.AddMailService(service);
return service;
}
调用交换服务器 API 时,包装在模拟块中。
public bool SendReply(string messageId, string response){
UserInfoHelper ui = new UserInfoHelper();
using(HostingEnvironment.Impersonate())
{
try
{
DC = new PrincipalContext(ContextType.Domain, Constant.QMS_DOMAIN);
GP = GroupPrincipal.FindByIdentity(DC, IdentityType.Name, "Domain Users");
ImpersonationContext = ((System.Security.Principal.WindowsIdentity)System.Threading.Thread.CurrentPrincipal.Identity).Impersonate();
//do stuff
}
catch(Exception e)
{
ErrorHelper.AddErrorMsg("SendReply: " + e);
}
}
return false;
}
最后,这很重要,必须设置客户端浏览器以在客户端计算机上进行委派。在 Chrome 中,您需要编辑注册表。在 FF 中,您需要在 about:config 中设置 uris 键。开箱即用的行为将因 kerberos 而失败。有关更多信息,请参阅此内容(https://answers.laserfiche.com/questions/50123/Does-single-sign-on-or-authentication-negotiation-not-work-on-Chrome-in-Weblink和https:// dev.chromium.org/administrators/policy-list-3#AuthNegotiateDelegateWhitelist)。
下面是我的原帖。
很长一段时间以来,我一直在对同一件事进行故障排除。看看这个(无法使用 HttpClient 对 ASP.NET Web Api 服务进行身份验证)。我已修改 Aspnet.config 文件无济于事。从我目前阅读的内容来看,System.Net.HttpWebRequest.GetResponse() 似乎在一个新线程上,并且模拟的凭据没有转移到新对象。我已将 IIS 身份验证提供程序设置为协商:kerberos 以确保委派应该/可以发生。
我应该创建一个备用服务帐户而不是使用我的帐户吗?
根据您的配置,即 IIS 位于负载平衡器和防火墙后面,您可能需要一个自定义服务帐户,例如 mydomain\my_service_account,它需要一个 SPN http/my.webserver.com。然而,我有这个设置,它并不是让这个工作的秘诀。我开始认为唯一可行的方法是在交换帐户上设置模拟(https://msdn.microsoft.com/en-us/library/office/dn722376(v=exchg.150)。 .aspx)。在此计划下,您在设置服务时会调用如下所示的内容。如果 IIS 上的服务帐户无权在 Exchange 服务器上模拟,这也不起作用。此外,您需要传递服务帐户的身份,而不是模拟用户的身份。
if(UserInfo.Email != null)
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, UserInfo.Email);
我希望有人可以提供比这更好的答案。以下是我目前在跟踪中看到的内容。
9: <Trace Tag="EwsResponseHttpHeaders" Tid="38" Time="2017-01-20 20:59:29Z"> HTTP/1.1 401 未经授权的服务器:Microsoft-IIS/7.5 WWW-Authenticate: Negotiate,NTLM X-技术支持:ASP.NET 日期:2017 年 1 月 20 日星期五 20:59:29 GMT 内容长度:0
</追踪>
10:GetUnreadMail ee:Microsoft.Exchange.WebServices.Data.ServiceRequestException:请求失败。远程服务器返回错误:(401) Unauthorized。---> System.Net.WebException:远程服务器返回错误:(401)未经授权。在System.Net.HttpWebRequest.GetResponse()
在 Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.Microsoft.Exchange.WebServices.Data.IEwsHttpWebRequest.GetResponse() 在 Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request) --- 内部异常堆栈跟踪结束 - -- 在 Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request) 在 Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(IEwsHttpWebRequest& request) 在 Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute()在 Microsoft.Exchange.WebServices.Data.ExchangeService.FindItems(FolderId parentFolderId,SearchFilter searchFilter,ViewBase 视图)在 Microsoft.Exchange.WebServices.Data.ExchangeService.FindItems(WellKnownFolderName parentFolderName,SearchFilter searchFilter, ViewBase view) at QDoc.Helpers.ExchangeHelper.GetUnreadMail(ExchangeParam ExchangeQueryParam, MailItemList ExchangeResults, String myDomain) 在 c:\Inet\QDoc\QDoc\Helpers\ExchangeHelper.cs:line 186