Пользователь Windows получает «доступ запрещен» с сервера Exchange

У меня есть веб-приложение MVC, использующее проверку подлинности Windows и веб-службы Exchange. В процессе разработки это работало замечательно, поскольку пул приложений в IIS на моей машине для разработки настроен для работы под моим пользователем Windows, а сервер Exchange Server находится в одном домене.

Однако на веб-сервере все наши приложения настроены для работы под системным пользователем, который имеет доступ ко всем серверам баз данных и т. Д. Соединение с базой данных использует встроенную защиту, поэтому я не могу выдать себя за пользователя на уровне приложения.

Я пытался выдать себя за текущего пользователя Windows с помощью кода следующим образом:

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

Затем класс, который реализует абстрактные методы:

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

Затем методы доступны следующим образом:

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

Это все еще работает на моей локальной машине разработчика, но независимо от того, что я делаю, пользователь, получающий доступ с сервера, получает отказ в доступе с сервера Exchange:

Ошибка запроса. Удаленный сервер возвратил ошибку: (401) Несанкционированный.

Я попытался оставить его с учетными данными по умолчанию:

this._service.UseDefaultCredentials = true;

И попытка вручную установить учетные данные для текущего (предположительно олицетворенного) пользователя:

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

Также я попробовал использовать ExchangeImpersonatedUserId объект с использованием адреса электронной почты:

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

который возвращает следующее исключение:

Учетная запись не имеет разрешения выдавать себя за запрошенного пользователя.

Ответы на вопрос(2)

Ваш ответ на вопрос