Спасибо Sideshowbarker за то, что он указал мне правильное направление.Я, наконец, выяснил фундаментальную проблему, с которой я боролся, и реализовал решение.
Основная проблема заключается в том, что наш сайт является внутренним сайтом, который использует встроенную защиту для соединений, и это создает несовместимость с поддержкой CORS и CORS.в IIS.Внешний интерфейс представляет собой интерфейс Angular 6 с веб-службой ASP.NET.Чтобы использовать встроенную безопасность, вы должны отключить анонимную аутентификацию.Кроме того, чтобы заставить аутентификацию работать, вы должны передать {withCredentials: true} с вашими запросами.Это прекрасно работает для запросов GET, потому что спецификация CORS не требует предварительных опций для этих запросов, а заголовок запроса GET будет иметь требуемый токен учетных данных для правильного разрешения.
Проблема вступает в игру сPUT запросы.CORS требует предварительный запрос OPTIONS для PUT, но запрос OPTIONS не включает учетные данные, даже если вы установили флаг withCredentials: true.Это означает, что вы должны включить анонимную аутентификацию, которая нарушит вашу встроенную безопасность.Немного подвох 22. Я не смог найти способ включить анонимный вход только для ОПЦИЙ.Я нашел пару постов StackOverflow, в которых утверждалось, что вы можете сделать это в IIS, но я не смог заставить это работать.Я также нашел сообщения от MS, в которых говорилось, что IIS не поддерживает эту функцию.Это означает, что вы должны написать собственный обработчик для запроса OPTIONS и сгенерировать правильный ответ, чтобы удовлетворить браузер.Есть несколько сообщений на эту тему, но лучше всего я нашел ответ Stu на эту тему 401 ответ на запрос CORS в IIS с включенной аутентификацией Windows
С незначительным улучшением, которое я смог получитьэто работать на меня.Мне нужна поддержка нескольких доменов в моей конфигурации системы, и я все еще получаю сообщение об ошибке, если я помещаю несколько URL-адресов в поле источника.Я использовал поле Origin в заголовке Request.Headers, чтобы получить текущее происхождение, и отправил это значение обратно в свой построенный заголовок ответа, как показано в приведенном ниже коде:
EDIT: Поработав некоторое время с этим, я понял, чтооригинальное решение имело недостаток.Мой оригинальный код явно не проверял источник, чтобы убедиться, что это разрешено.Как я уже говорил ранее, это было нормально для операций GET, потому что GET все равно потерпел бы неудачу (и вызов OPTIONS в любом случае необязателен для GET), но для PUT клиент передал бы вызов OPTIONS и сделал бы запрос PUT и получил бы ошибку в ответе.Тем не менее, сервер все равно будет выполнять запрос PUT, так как CORS принудительно выполняется на стороне клиента.Это приведет к вставке или обновлению данных, когда это не должно происходить.Решение этой проблемы заключается в явной проверке обнаруженного источника по списку источников CORS, который хранится в web.config, и возвращает статус 403 и пустое значение источника, если запрашивающий источник недействителен.Обновленный код указан ниже
protected void Application_BeginRequest(object sender, EventArgs e)
{
// Declare local variables to store the CORS settings loaded from the web.config
String origins;
String headers;
String methods;
// load the CORS settings from the webConfig file
origins = ConfigurationManager.AppSettings["corsOrigin"];
headers = ConfigurationManager.AppSettings["corsHeader"];
methods = ConfigurationManager.AppSettings["corsMethod"];
if (Request.HttpMethod == "OPTIONS")
{
// Get the Origin from the Request header. This should be present for any cross domain requests
IEnumerable<string> headerValues = Request.Headers.GetValues("Origin");
var id = headerValues.FirstOrDefault();
String httpOrigin = null;
// Assign the origin value to the httpOrigin string.
foreach (var origin in headerValues)
{
httpOrigin = origin;
}
// Construct the Access Control headers using the derived origin value and the desired content.
if (httpOrigin == null) httpOrigin = "*";
// Check to see if the origin is included in the CORS origin list
if (origins.IndexOf(httpOrigin) < 0)
{
// This has failed the CORS check so send a blank origin list and a 403 status (forbidden)
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "");
HttpContext.Current.Response.StatusCode = 403;
}
else
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", httpOrigin);
HttpContext.Current.Response.StatusCode = 200;
}
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With,content-type, Content-Type, Accept, X-Token");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Credentials", "true");
var httpApplication = sender as HttpApplication;
httpApplication.CompleteRequest();
}
}
Этот код был добавлен в метод Application_BeginRequest в файле global.asax.cs.Кроме того, подпись этого метода была изменена, чтобы включить объект отправителя, как показано здесь: protected void Application_BeginRequest (отправитель объекта, EventArgs e) {Это теперь будет генерировать ответ на запрос браузера OPTIONS, который удовлетворяет требованию CORS, и последующий GET будет по-прежнемупройти валидацию также, поэтому я не верю, что есть какое-либо негативное влияние на безопасность.
Последний элемент состоит в том, чтобы создать ваши GET и PUT, чтобы они включали информацию о полномочиях.Примеры запросов приведены ниже: let url = environment.base_url + 'api / SubDoc / GetDocument? DocID =' + docID;
this.httpClient.get(url,
{
withCredentials: true
})
.subscribe(
response => {
console.log(response);
newData = response;
this.currentDocument = newData;
}
);
и
body = { "GroupID": groupID, "ContactID": contact.ContactID, "IsActive": isActive }
let url = this.base_url + 'api/ContactGroup/Put';
this.httpClient.put(url, body,
{
headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
withCredentials: true
})
.subscribe(
response=>{
let temp:number;
temp = parseInt(response.toString(),10);
if(!isNaN(temp)){
this.groupID = temp;
}
}
);
Надеемся, это сохраниткто-то еще пережил дни боли и разочарования, пытаясь заставить CORS работать с Angular 6, ASP.NET и интегрированной безопасностью