Windows Benutzer, dem der Zugriff vom Exchange-Server verweigert wird

Ich habe eine MVC-Webanwendung, die Windows-Authentifizierung und Exchange-Webdienste verwendet. Während der Entwicklung hat dies hervorragend funktioniert, da der Anwendungspool in IIS auf meinem Entwicklungscomputer so eingestellt ist, dass er unter meinem Windows-Benutzer ausgeführt wird und sich der Exchange Server in derselben Domäne befindet.

Auf dem Webserver sind jedoch alle unsere Anwendungen so eingestellt, dass sie unter einem Systembenutzer ausgeführt werden, der Zugriff auf alle Datenbankserver usw. hat. Die Datenbankverbindung verwendet die integrierte Sicherheit, sodass ich mich nicht als Benutzer über eine Anwendungsebene ausgeben kann.

Ich habe versucht, den aktuellen Windows-Benutzer über den Code wie folgt zu imitieren:

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 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 wird auf die Methoden wie folgt zugegriffen:

public static class ExchangeServiceExtensions
{
    public static async Task<string> CreateMeetingAsync(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end)
    {
        ExchangeServiceImpersonator serviceImpersonator = new ExchangeServiceExtensionsBase();
        return await serviceImpersonator.CreateMeetingAsync(from, to, subject, body, location, begin, end);
    }
}

Dies funktioniert immer noch auf meinem lokalen Dev-Rechner, aber egal was ich tue, der Benutzer, der vom Server aus zugreift, erhält vom Exchange-Server immer wieder einen verweigerten Zugriff:

Die Anfrage ist fehlgeschlagen. Der Remote-Server hat einen Fehler zurückgegeben: (401) Nicht autorisiert.

Ich habe versucht, die Standardanmeldeinformationen beizubehalten:

this._service.UseDefaultCredentials = true;

Und Sie versuchen, die Anmeldeinformationen manuell auf den aktuellen (vermeintlich imitierten) Benutzer festzulegen:

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

Auch habe ich versucht mit dem ExchangeImpersonatedUserId Objekt unter Verwendung der E-Mail-Adresse:

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

, das die folgende Ausnahme zurückgibt:

Das Konto hat keine Berechtigung, sich als der angeforderte Benutzer auszugeben.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage