Мне не очень нравится .NET, и я нахожу следующие сложности.
У меня есть пример использования, подобный этому: Как заставить HttpClient передавать учетные данные вместе с запросом?
По сути, у меня есть веб-приложение .NET (в которое пользователи могут войти), работающее в облаке Azure (это приложение, работающее в SharePoint, я не знаю, может ли это быть уместно).
В серверной части этого веб-приложения я реализовал контроллер ApiController , который должен вызывать еще один второй REST API.
Этот второй API-интерфейс работает в другой среде (это должен быть компьютер в Azure), но обе эти среды должны каким-то образом «совместно использовать» учетные данные. Я думаю, что это очень важный момент, я пытаюсь объяснить ситуацию на практике:
У меня есть веб-приложение .NET , работающее в среде A . Пользователь может войти в это приложение, вставив свои учетные данные.
В другой среде B использует API , который должно вызывать предыдущее веб-приложение. Конечная точка выглядит примерно так: *http://MY_MACHINE_NAME.westeurope.cloudapp.azure.com:8081/PI_WebAPI/API_TO_BE_CALLED (как вы можете видеть, она работает на лазурной виртуальной машине).
Веб-приложение и API работают в двух разных средах, но имеют общие учетные данные (я не знаю деталей, но это работает таким образом, я думаю, что они должны быть на тот же домен ). Доказательством этого утверждения является то, что если я вызываю мой API (из браузера), он спрашивает мои учетные данные пользователя (в всплывающем окне borwser). Но если я сначала войду в свое веб-приложение (работающее в среде A), а затем вызову свой API (работающий в среде B) на другой вкладке браузера, он получит прямой доступ, потому что знает, что я вошел в систему.
Что мне нужно сделать, так это разрешить бэкэнду моего веб-приложения (работающего в среде A) вызывать этот API (работающий в среде B) с использованием учетных данных зарегистрированного пользователя.
Итак, я пытался реализовать предыдущую почтовую стратегию.
Я реализовал свой контроллер следующим образом:
[SharePointContextWebAPIFilter]
[HttpGet]
[ActionName("GetAooList2")]
public IHttpActionResult GetAooList2()
{
Console.WriteLine("INTO GetAooList2()");
string jsonRequest = urlBaseProtocolloApi + "/api/ProtocollaMail/GetListAOO";
var wi = (System.Security.Principal.WindowsIdentity)HttpContext.Current.User.Identity;
var wic = wi.Impersonate();
..............................................................
..............................................................
..............................................................
return Ok("TEST");
}
Моя идея состоит в том, чтобы получить учетные данные зарегистрированного пользователя и олицетворять эти учетные данные перед выполнением моего вызова.
Проблема в том, что при выполнении метода Impersonate () я получаю следующее исключение:
System.InvalidOperationException: 'An anonymous identity cannot perform an impersonation.'
Так что я думаю, что он не может восстановить личность. Заглядывая в объект wi (тот, для которого я вызываю метод impersonate ()), я обнаружил свойство IsAnonymous , установленное в true , и мне кажется, что не содержит информации о зарегистрированном пользователе.
Как объяснено, я не в .NET и, возможно, я что-то упускаю, что?
Используя этот код, какого пользователя я пытаюсь выдать?
Я также пытался сделать это, используя эту другую реализацию:
public class MailProtocolloController : ApiController
{
private String urlBaseProtocolloApi = "http://MY_MACHINE_NAME.westeurope.cloudapp.azure.com:8081/PI_WebAPI";
[SharePointContextWebAPIFilter]
[HttpGet]
[ActionName("GetAooList")]
public IHttpActionResult GetAooList()
{
string jsonRequest = urlBaseProtocolloApi + "/API_TO_BE_CALLED";
CredentialCache credCache = new CredentialCache();
credCache.Add(new Uri(jsonRequest), "NTLM", CredentialCache.DefaultNetworkCredentials);
HttpWebRequest spRequest = (HttpWebRequest)HttpWebRequest.Create(jsonRequest);
spRequest.Credentials = credCache;
spRequest.UserAgent = "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0";
spRequest.Method = "GET";
spRequest.Accept = "application/json;odata=verbose";
HttpWebResponse endpointResponse = (HttpWebResponse)spRequest.GetResponse();
...............................................................................
...............................................................................
...............................................................................
}
}
Как вы видите, я пытаюсь получить DefaultNetworkCredentials моего веб-приложения (которое я ожидал получить в качестве учетных данных зарегистрированного пользователя, которые я должен использовать для выполнения вызова моего второго REST API). Но это не работает, например, когда вы выполняете эту строку, выполните следующие действия:
HttpWebResponse endpointResponse = (HttpWebResponse)spRequest.GetResponse();
Я получаю следующее исключение:
System.Net.WebException: 'The remote server returned an error: (401) Unauthorized.'
Но я думаю, что это может быть что-то вроде "хорошего пути" (с использованием протокола NTLM ), потому что если вместо этого использовать DefaultNetworkCredentials , я вручную устанавливаю свои учетные данные в код работает нормально, и я правильно получаю ответ REST API.
Я сделал это следующим образом:
[SharePointContextWebAPIFilter]
[HttpGet]
[ActionName("GetAooList")]
public IHttpActionResult GetAooList()
{
Console.WriteLine("INTO GetAooList()");
string jsonRequest = urlBaseProtocolloApi + "/API_TO_BE_CALLED";
NetworkCredential myCreds = new NetworkCredential("MY_USERNAME", "MY_PSWD", "THE_DOMAIN");
CredentialCache credCache = new CredentialCache();
credCache.Add(new Uri(jsonRequest), "NTLM", myCreds);
//credCache.Add(new Uri(jsonRequest), "NTLM", CredentialCache.DefaultNetworkCredentials);
HttpWebRequest spRequest = (HttpWebRequest)HttpWebRequest.Create(jsonRequest);
spRequest.Credentials = credCache;
spRequest.UserAgent = "Mozilla/4.0+(compatible;+MSIE+5.01;+Windows+NT+5.0";
spRequest.Method = "GET";
spRequest.Accept = "application/json;odata=verbose";
HttpWebResponse endpointResponse = (HttpWebResponse)spRequest.GetResponse();
..........................................................................................
..........................................................................................
..........................................................................................
}
Как вы можете видеть, используя эту строку:
NetworkCredential myCreds = new NetworkCredential("MY_USERNAME", "MY_PSWD", "THE_DOMAIN");
, в котором я устанавливаю имя пользователя , пароль и DOMAIN (веб-приложение и API должны работать в разных средах, но на тот же домен ) он работает нормально и API правильно называется.
Очевидно, я не могу смоделировать эту информацию в коде моего контроллера. Мне нужен способ получить эти учетные данные и использовать их.
Есть идеи? Как мне это сделать? Чего мне не хватает?