1

Я занимаюсь разработкой сайта интрасети, который будет использоваться в локальной сети. В корпоративной среде пользователи могут использовать этот сайт, например OWA, они могут видеть свои входящие, отправлять письма и т. Д. Чтобы добиться этого, я использую EWS Managed Api 2.2 для подключения Exchange Server (2010_sp1). Я разрабатываю ASP.NET MVC 5. Я разрабатываю на своем компьютер с IIS 10.0 installed.While Я развивается с IISExpress, не было никаких проблем, чтобы соединиться с учетными данными по умолчанию>EWS Managed API Double Hop

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1); 
service.UseDefaultCredentials = true; 

Я понимаю, что это происходит потому, что IIS Express не использовать свои полномочия в качестве учетных данных по умолчанию, так что было не ошибка для подключения службы. Но когда я запускаю этот код с IIS на моем компьютере (с моими учетными данными в Удостоверение пула приложений с использованием сети САШ, олицетворение включена, включена проверка подлинности Windows и ПЕРЕГОВОРЫ поставщиков/NTML) тождества загрузить правильные

HttpContext.User.Identity.Name > xxx\billgates 
WindowsIdentity.GetCurrent().Name> xxx\billgates 

но сервис обмена возвращается в след эти>

<Trace Tag="EwsRequestHttpHeaders" Tid="29" Time="2017-01-02 08:03:04Z"> 
POST /EWS/Exchange.asmx HTTP/1.1 
Content-Type: text/xml; charset=utf-8 
Accept: text/xml 
User-Agent: ExchangeServicesClient/15.00.0913.015 
Accept-Encoding: gzip,deflate 
</Trace> 

<Trace Tag="EwsRequest" Tid="29" Time="2017-01-02 08:03:04Z" Version="15.00.0913.015"> 
    <?xml version="1.0" encoding="utf-8"?> 
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Header> 
     <t:RequestServerVersion Version="Exchange2010_SP1" /> 
    </soap:Header> 
    <soap:Body> 
     <m:GetFolder> 
     <m:FolderShape> 
      <t:BaseShape>AllProperties</t:BaseShape> 
     </m:FolderShape> 
     <m:FolderIds> 
      <t:DistinguishedFolderId Id="inbox" /> 
     </m:FolderIds> 
     </m:GetFolder> 
    </soap:Body> 
    </soap:Envelope> 
</Trace> 

<Trace Tag="EwsResponseHttpHeaders" Tid="29" Time="2017-01-02 08:03:04Z"> 
HTTP/1.1 401 Unauthorized 
Server: Microsoft-IIS/7.5 
WWW-Authenticate: Negotiate,NTLM 
X-Powered-By: ASP.NET 
Date: Mon, 02 Jan 2017 08:03:04 GMT 
Content-Length: 0 
</Trace> 

когда я использую EWEditor (https://ewseditor.codeplex.com/) Я видел, что нет ошибок с подключения с учетными данными по умолчанию и при запуске Klist в PowerShell есть tickes как Kerberos>

Se rver: krbtgt/[email protected] Тип шифрования KerbTicket: RSADSI RC4-HMAC (NT) Время окончания: 1/2/2017 21:35:37 Время продления: 1/9/2017 11:35:37

Сервер: krbtgt/[email protected] KerbTicket Тип шифрования: Неизвестный (18) End Time: 1/2/2017 21:35:37 Продлить время : 1/9/2017 11:35:37

Сервер: HTTP/[email protected] KerbTicket Тип шифрования: RSADSI RC4-HMAC (NT) End Time: 1/2/2017 21:35:37 Время продления: 1/9/2017 11:35:37

Сервер: HTTP/[email protected] KerbTicket Тип шифрования: RSADSI RC4-HMAC (NT) End Time: 1/2/2017 21:35:37 Продлить время: 1/9/2017 11:35:37

Сервер: HTTP/[email protected] KerbTicket Тип шифрования: Неизвестный (18) End Time: 1/2/2017 21 : 35: 37 Продлить время: 1/9/2017 11:35:37

Сервер: ldap/[email protected] KerbTicket Encryption Type: Неизвестный (18) End Время: 1/2/2017 21:35:37 Время продления: 1/9/2017 11:35:37

с этими билетами Я предполагаю, что kerberos работает, мой первый вопрос заключается в том, что я прав? Могу ли я быть уверенным, что эти билеты гарантируют, что keberos работает с серверами клиентского доступа?

Во время поиска этой проблемы я увидел, что эта проблема очень похожа на проблему с двойным прыжком, подобную этому блогу, говорит>https://blogs.msdn.microsoft.com/dhruvkh/2012/04/15/the-double-hop-dogma/ . Фактически моя проблема в точности как этот пост.Как этот пост рекомендует ли я использовать свой счет в качестве учетной записи службы и добавить СПбОЕ на мой счет и написать, что в Удостоверение пула приложений в IIS

SPNs, что я использовал

HTTP/autodiscover.xxxxxx.xxx.xx

http/posta.xxxxxx.xxx.xx

ПРИМЕЧАНИЕ. Я уверен, что эти SPN не используются.

После добавления spns я также проверяю «Доверяйте этот компьютер делегированию любой службе (только Kerberos)». на вкладке «Делегация» моей учетной записи пользователя.

Мой другой вопрос в том, что, как пост предложить на 3 этапе https://technet.microsoft.com/en-us/library/ff808312(v=exchg.141).aspx я должен создать альтернативную учетную запись службы вместо того, чтобы использовать мой счет? Если я должен использовать ASA, следует добавить учетные данные учетной записи Alternate службы в IIS Удостоверение пула приложений ?

Спасибо за помощь.

ответ

1

Update from previous post. I have gotten this to work and my current settings are not what I would have expected to produce results. I'm using IIS 8.5 on Win 2012 R2

  1. AppPool: установлен интегрированный трубопровод
  2. AppPool: Нагрузка пользователя: Ложные
  3. AppPool: IIS работает под учетной записью службы домена сконфигурированной для делегирования
  4. В App> Аутентификация , ASP.Net олицетворения: Отключено. Аутентификация Windows: разрешено w/kernel mode off. Поставщики услуг: Согласование: Keberos.
  5. Редактор конфигурации> system.webServer/security/authentication/windowsAuthentication useAppPoolCredentials: True. useKernelMode: Ложные
  6. Локальная политика безопасности> Локальные политики> Назначение прав пользователя: Учетная запись службы должна быть в группе, указанной в политике «Олицетворение клиента после проверки подлинности»

Modification to 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> 

Below is the service source that is working. I left in all the commented out code so you can see everything that I have been trying. Note only some of the active code is needed.

 //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; 
     } 

When calling the exchange server API, wrap in an impersonation block.

 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; 
    } 

Lastly, and this is a important, the client browsers have to be set up for delegation on the client machines. In Chrome you need to edit the registry. In FF you need to set up the uris keys in about:config. Out of the box behavior will fail with kerberos. See this for more info (https://answers.laserfiche.com/questions/50123/Does-single-sign-on-or-authentication-negotiation-not-work-on-Chrome-in-Weblink and https://dev.chromium.org/administrators/policy-list-3#AuthNegotiateDelegateWhitelist).

Registry Modification for Chrome

Below was my original post.

Я устранение неполадок то же самое в течение длительного времени. Взгляните на это (Unable to authenticate to ASP.NET Web Api service with HttpClient). Я изменил файл Aspnet.config безрезультатно. Из того, что я прочитал до сих пор, похоже, что System.Net.HttpWebRequest.GetResponse() находится в новом потоке, а выданные учетные данные не переносятся на новый объект. Я установил провайдер аутентификации IIS для переговоров: kerberos, чтобы убедиться, что делегирование должно/должно произойти.

should I create an Alternate Service Account instead of using my account?

В зависимости от вашей конфигурации, т.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: < трассировки Тэг = " EwsResponseHttpHeaders " Врем = Время = " 2017-01-20 20: 59: 29Z " > HTTP/1.1 401 Несанкционированное Сервер: Microsoft-IIS/7.5 WWW- Аутентифицировать: Negotiate, NTLM X-Powered-By: ASP.NET Дата: Пт, 20 января 2017 20:59:29 GMT Content-Length: 0

</Трассировка >

10: GetUnreadMail ee: Microsoft.Exchange.WebServices.Data.ServiceRequestException: запрос не выполнен. Удаленный сервер ответил на ошибку: (401) Неавторизованный. --- > 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) --- Конец внутренней трассировки стека исключений --- по запросу Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse (IEwsHttpWebRequest) в Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest (IEwsHttpWebRequest &) на Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.Execute() на Microsoft.Exchange.WebServices.D ata.ExchangeService.FindItems (FolderId parentFolderId, SearchFilter searchFilter, ViewBase вид) на Microsoft.Exchange.WebServices.Data.ExchangeService.FindItems (WellKnownFolderName parentFolderName, SearchFilter searchFilter, ViewBase вид) на QDoc.Helpers.ExchangeHelper.GetUnreadMail (ExchangeParam ExchangeQueryParam , ExchangeResults MailItemList, String myDomain) в c: \ Inet \ QDoc \ QDoc \ Helpers \ ExchangeHelper.cs: строка 186

Смежные вопросы