Был заблокирован политикой CORS: Ответ на предполетный запрос не проходит проверку контроля доступа
Я создал сервер путешествий. Он работает нормально, и мы можем сделать POST
запрос от Insomnia, но когда мы делаем POST
запрос по axios на нашем интерфейсе, он отправляет ошибку:
has been blocked by CORS policy: Response to preflight request doesnt pass access control check: It does not have HTTP ok status.
Наш запрос на axios:
let config = {
headers: {
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*',
}
}
let data = {
"id": 4
}
axios.post('http://196.121.147.69:9777/twirp/route.FRoute/GetLists', data, config)
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
});
}
Мой файл go:
func setupResponse(w *http.ResponseWriter, req *http.Request) {
(*w).Header().Set("Access-Control-Allow-Origin", "*")
(*w).Header().Set("Access-Control-Allow-Methods", "POST,GET,OPTIONS, PUT, DELETE")
(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}
func WithUserAgent(base http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ua := r.Header.Get("Jwt")
ctx = context.WithValue(ctx, "jwt", ua)
r = r.WithContext(ctx)
setupResponse(&w, r)
base.ServeHTTP(w, r)
})
}
const (
host = "localhost"
port = 5432
user = "postgres"
password = "postgres"
dbname = "postgres"
)
func main() {
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
server := &s.Server{psqlInfo}
twirpHandler := p.NewFinanceServiceServer(server, nil)
wrap := WithUserAgent(twirpHandler)
log.Fatalln(http.ListenAndServe(":9707", wrap))
}
Как я уже говорил в Insomnia, он прекрасно работает, но когда мы делаем POST
запрос axios, в консоли браузера появляется следующее:
был заблокирован политикой CORS: Ответ на предпечатный запрос не прошел проверку контроля доступа: не имеет статуса HTTP ok.
Ответы
Ответ 1
Я считаю, что это самый простой пример:
header := w.Header()
header.Add("Access-Control-Allow-Origin", "*")
header.Add("Access-Control-Allow-Methods", "DELETE, POST, GET, OPTIONS")
header.Add("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
Вы также можете добавить заголовок для Access-Control-Max-Age
и, конечно, вы можете разрешить любые заголовки и методы, которые вы пожелаете.
Наконец, вы хотите ответить на первоначальный запрос:
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
Изменить (июнь 2019): теперь мы используем гориллу для этого. Их вещи поддерживаются более активно, и они занимаются этим очень долго. Оставив ссылку на старую, на всякий случай.
Старая рекомендация по промежуточному программному обеспечению ниже: Конечно, для этого, вероятно, будет проще использовать промежуточное программное обеспечение. Я не думаю, что использовал это, но этот, кажется, очень рекомендуется.
Ответ 2
Включите перекрестные запросы в ASP.NET Web API, нажмите для получения дополнительной информации
Включите CORS в приложении WebService. Сначала добавьте пакет CORS NuGet. В Visual Studio в меню Сервис выберите Диспетчер пакетов NuGet, затем выберите Консоль диспетчера пакетов. В окне консоли диспетчера пакетов введите следующую команду:
Install-Package Microsoft.AspNet.WebApi.Cors
Эта команда устанавливает последний пакет и обновляет все зависимости, включая основные библиотеки Web API. Используйте флаг -Version для указания конкретной версии. Для пакета CORS требуется Web API 2.0 или более поздней версии.
Откройте файл App_Start/WebApiConfig.cs. Добавьте следующий код в метод WebApiConfig.Register:
using System.Web.Http;
namespace WebService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Затем добавьте атрибут [EnableCors] в ваши методы контроллера/контроллера
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace WebService.Controllers
{
[EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
public class TestController : ApiController
{
// Controller methods not shown...
}
}
Включить перекрестные запросы (CORS) в ASP.NET Core
Ответ 3
Этот ответ объясняет, что происходит за кулисами, и основы того, как решить эту проблему на любом языке. Для справки см. документы MDN по этой теме.
Вы делаете запрос на URL-адрес от JavaScript, работающего на одном домене (скажем, domain-a.com), к API, работающему на другом домене (domain-b.com). Когда вы делаете это, браузер должен спросить domain-b.com, можно ли разрешить запросы от domain-a.com. Это делается с помощью HTTP-запроса OPTIONS
. Затем в ответе сервер на domain-b.com должен предоставить (как минимум) следующие HTTP-заголовки с надписью "Да, все в порядке":
HTTP/1.1 204 No Content // or 200 OK
Access-Control-Allow-Origin: https://domain-a.com // or * for allowing anybody
Access-Control-Allow-Methods: POST, GET, OPTIONS // What kind of methods are allowed
... // other headers
Если вы находитесь в Chrome, вы можете увидеть, как выглядит ответ, нажав клавишу F12 и перейдя на вкладку "Сеть", чтобы увидеть ответ, который дает сервер на domain-b.com.
Итак, вернемся к минимуму первоначального ответа @threeve:
header := w.Header()
header.Add("Access-Control-Allow-Origin", "*")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
Это позволит любому человеку из любого места получить доступ к этим данным. Другие заголовки, которые он включил, необходимы по другим причинам, но эти заголовки - необходимый минимум для выполнения требований CORS (Cross Origin Resource Sharing).
Ответ 4
Представленное решение здесь является правильным. Однако та же самая ошибка может также произойти из-за ошибки пользователя, когда ваш метод запроса конечной точки совпадает с методом, который вы используете при выполнении запроса.
Например, конечная точка сервера определяется с помощью "RequestMethod.PUT", пока вы запрашиваете метод как POST.