0

Ich habe eine MVC-Webanwendung verwendet Windows-Authentifizierung und Exchange-Webdienste. Während der Entwicklung funktionierte das großartig, da der Anwendungspool in IIS auf meinem Entwicklungscomputer so eingestellt ist, dass er unter meinem Windows-Benutzer ausgeführt wird und der Exchange Server sich in derselben Domäne befindet.Windows-Benutzer erhalten "Zugriff verweigert" von Exchange-Server

Auf dem Webserver werden jedoch alle Anwendungen so ausgeführt, dass sie unter einem Systembenutzer ausgeführt werden, der Zugriff auf alle Datenbankserver usw. hat. Die Datenbankverbindung verwendet integrierte Sicherheit. Daher kann ich einen Benutzer nicht über eine Anwendungsebene imitieren.

Ich habe versucht, die aktuelle Windows-Benutzer über den Code zum Imitieren wie folgt:

public abstract class ExchangeServiceImpersonator 
{ 
    private static WindowsImpersonationContext _ctx; 

    public Task<string> CreateMeetingAsync(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end) 
    { 
     var tcs = new TaskCompletionSource<string>(); 
     EnableImpersonation(); 

     try 
     { 
      tcs.TrySetResult(CreateMeetingImpersonated(from, to, subject, body, location, begin, end)); 
     } 
     catch(Exception e) 
     { 
      tcs.TrySetException(e); 
     } 
     finally 
     { 
      DisableImpersonation(); 
     } 

     return tcs.Task; 
    } 

    public abstract string CreateMeetingImpersonated(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end); 

    private static void EnableImpersonation() 
    { 
     WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity; 
     _ctx = winId.Impersonate(); 
    } 

    private static void DisableImpersonation() 
    { 
     if (_ctx != null) 
      _ctx.Undo(); 
    } 
} 

Dann wird die Klasse, die die abstrakten Methoden implementiert:

public class ExchangeServiceExtensionsBase : ExchangeServiceImpersonator 
{ 
    private ExchangeService _service; 

    public ExchangeService Service 
    { 
     get 
     { 
      if (this._service == null) 
      { 
       this._service = new ExchangeService(ExchangeVersion.Exchange2013); 
       this._service.Url = new Uri(WebConfigurationManager.AppSettings["ExchangeServer"]); 
       this._service.UseDefaultCredentials = true; 
      } 

      return this._service; 
     } 
     set { return; } 
    } 

    public override string CreateMeetingImpersonated(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end) 
    { 
     //this.Service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, from); 

     Appointment meeting = new Appointment(Service); 
     string meetingID = Guid.NewGuid().ToString(); 

     meeting.Subject = subject; 
     meeting.Body = "<span style=\"font-family:'Century Gothic'\" >" + body.Replace(Environment.NewLine, "<br/>") + "<br/><br/>" + 
      "<span style=\"color: white;\">Meeting Identifier: " + meetingID + "</span></span><br/><br/>"; 
     meeting.Body.BodyType = BodyType.HTML; 
     meeting.Start = begin; 
     meeting.End = end; 
     meeting.Location = location; 
     meeting.ReminderMinutesBeforeStart = 60; 

     foreach (string attendee in to) 
     { 
      meeting.RequiredAttendees.Add(attendee); 
     } 
     meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy); 

     return meetingID; 
    } 
} 

Dann werden die Methoden sind Zugriff wie folgt:

Dies funktioniert immer noch auf meinem lokalen Dev-Maschine, aber egal was ich tue, hält der Benutzer vom Server Zugriff auf einen Zugriffs immer vom Exchange-Server verweigert:

The request failed. The remote server returned an error: (401) Unauthorized.

Ich habe versucht, es auf Standard-Anmeldeinformationen zu verlassen:

this._service.UseDefaultCredentials = true; 

Und die manuell eingestellte Versuch, Anmeldeinformationen zum aktuellen (imitierten angeblich) Benutzer:

this._service.Credentials = new WebCredentials(CredentialCache.DefaultNetworkCredentials); 

Außerdem habe ich versucht, das Exchange ImpersonatedUserId Objekt mit der E-Mail-Adresse:

this._service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, from); 

, die die folgende Ausnahme zurückgibt:

The account does not have permission to impersonate the requested user.

+1

vielleicht hilft dies http://stackoverflow.com/questions/9220900/wrong-mailbox-items-bein-retredived-using-exchange-web-services-managed-api-in-c/9242792#9242792 – Thorarins

Antwort

2

standardmäßig und als Sicherheitsmaßnahme, wird Windows verhindern, dass Sie Ihre Anmeldeinformationen aus dem Web-Server auf Exchange zu delegieren. Dies bedeutet, dass Sie nicht die Identität des Benutzers annehmen können, der auf Ihre Website zugreift.

Dies wird als "Server-Doppelsprung" -Szenario bezeichnet. Der erste "Hop" geht vom Computer des Benutzers zum Webserver und der zweite "Hop" vom Webserver zum Exchange-Server (Google liefert Ihnen viele Treffer auf dem Server-Doppelsprung).

Dies ist eine gute Sache, da es verhindern wird, dass sich Hacker auf Ihren Servern bewegen.

Der Grund, warum es auf Ihrem Entwicklungscomputer funktioniert, ist, dass es nur einen "Sprung" von Ihrem lokalen Webserver zum Exchange-Server gibt.

Um es zu lösen, müssen Sie dem Webserver ermöglichen, die Anmeldeinformationen an den Exchange-Server zu delegieren. Dies nennt sich Kerberos-Delegation und muss von Ihrem Systemadministrator irgendwie im Active Directory eingerichtet werden (was meines Wissens nach nicht der Fall ist).

+0

Forwarded eine Abfrage an den Serveradministrator zum Einrichten der Kerberos-Delegierung.Muss warten und sehen, was sie sagen. – Carel