Хочется сказать несколько полезных на наш взгляд замечаний по поводу защиты CORS в браузерах.
Первое и наверное самое главное для понимания, что в условиях так называемого кросс доменного запроса соединение с хвостом всё-таки устанавливается.
То есть на компьютере например выполняется некоторая программа TCP сервер и слушает она localhost:33333 например. Далее браузер, запущенный на этом же компьютере, открывает страницу сайта kkmspb.ru, на которой в какой-то произвольный момент делается ajax запрос, который обращается к localhost:33333.
В результате срабатывает защита CORS в браузере. Но самое важное, что соединение с TCP сервером все таки происходит и заголовки передаются и ответ браузер принимает, данные браузер принимает.
Данные имеется ввиду как минимум заголовки в виде имя:значение.
OPTIONS
Скорее всего браузер сначала пошлет на localhost OPTIONS запрос. Далее сервер localhost ответит, но браузер , в котором открыта страница сайта kkmspb.ru, заблокирует ответ.
По факту получается, что маякнуть локальному компьютеру можно. То есть например Виндоус программа, у которой реализован TCP сервер на порту например 33333 сможет узнать, что в браузере на странице сайта kkmspb.ru произошло какое-то действие и что надо что-то локально в программе сделать.
При этом антивирусы и брандмауэры вроде не мешают. То есть а данном случае не надо открывать порт 33333 наружу, по-видимому потому что и браузер и программа сервер работают на одном ПК.
Рабочий вариант, когда все работает
Итак код в студию. Вот есть простой ajax запрос со страницы (не важно какой) на сайте kkmspb.ru:
var jqXHR = $.ajax({
url: url1,
method: 'GET',
//processData: false,
//crossDomain:true,
//contentType: "application/json",
//dataType: 'json',
async: true,
//dataType: 'jsonp',
headers: {
'Receipt_hash':hash
},
success: function(data , status , jqXHR)
{
console.log('success')
console.log('jqXHR.readyState:'+jqXHR.readyState)
console.log('status:'+status)
console.log('jqXHR.statusText:'+jqXHR.statusText)
},
error: function(jqXHR, status, errorMsg)
{
//wait_spin(false,nn)
console.log('Ошибка: ' +status +' errorMsg:'+errorMsg)
console.log('jqXHR.readyState:'+jqXHR.readyState)
console.log('status : '+status)
console.log('jqXHR.statusText:'+jqXHR.statusText)
}
});
Когда он начинает выполняться сначала посылается OPTIONS запрос серверу localhost:33333 (он же url1). На всякий случай надо отметить, что у нас Яндекс браузер. Вот содержание запроса:
OPTIONS / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: ru,en;q=0.9
Access-Control-Request-Headers: receipt_hash
Access-Control-Request-Method: GET
Access-Control-Request-Private-Network: true
Connection: keep-alive
Host: localhost:33333
Origin: https://kkmspb.ru
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 YaBrowser/24.4.0.0 Safari/537.36
Сервер TCP у нас написан на Qt 4, скачать проект можно ниже в конце страницы (там все банально). Итак сервер отвечает на OPTIONS запрос у нас так (буквально):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://kkmspb.ru
Access-Control-Allow-Headers: receipt_hash
Content-Length: 0
Итак первый запрос прошел нормально, но дело не в этом. Дело в том, что localhost:33333 ответил на OPTIONS запрос нужными заголовками (выделены пожирнее).
Обратите особо внимание на Access-Control-Allow-Headers. Именно на нем мы потеряли большую часть времени пока бились, чтобы удовлетворить требования CORS. Сначала заголовок клиент добавляет заголовок receipt_hash в Access-Control-Request-Headers, но также браузер ждет и в ответе сервера такое же название в заголовке Access-Control-Allow-Headers (проверено на практике на 100%). То есть мы не можем абы как передавать кастомные заголовки, нам надо от сервера получить разрешение конкретно на каждое наименование кастомного заголовка.
Далее основной запрос GET или POST
После того как браузер получит нужные ему заголовки:
Access-Control-Allow-Origin: https://kkmspb.ru
Access-Control-Allow-Headers:access-control-allow-headers
он пошлет основной запрос, чтобы получить данные, вот их обмен:
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: ru,en;q=0.9
Connection: keep-alive
Host: localhost:33333
Origin: https://kkmspb.ru
Receipt_hash: d634ab158c36480152753c071d8dfc36
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 YaBrowser/24.4.0.0 Safari/537.36
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "YaBrowser";v="24.4", "Yowser";v="2.5"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
от ответ:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://kkmspb.ru
Content-Length: 138
Content-Type: application/json
Еще вот, что получает и отвечает TCP сервер:

Итоги
Какие итоги можно подвести? CORS вроде работает и даже как надо, но надо проверять на всех браузерах (а у них еще версии имеются). Но допустим все работает как надо.
И тут выясняется, что теперь преград к защите своего программного обеспечения (софта) нет Господа.
Дело в том, что сами программы написанные для десктопа ломаются за разумные деньги. Но вы скажете , что можно выносить свой софт на интернет сервер - и будете правы.
Но главная проблема таких CRM, CMS и т.д. "была" , что через них трудно управлять локально подключенным оборудованием. Теперь вы знаете, что такой проблемы нет.
Файлы для скачивания
*
слушает порт localhost:33333, показывает как надо работать с CORS