Пользователь 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);
который возвращает следующее исключение:
Учетная запись не имеет разрешения выдавать себя за запрошенного пользователя.