已被 CORS 策略阻止: 对飞行前请求的响应没有通过访问控制检查

我创建了旅行服务器。它工作得很好,我们可以通过 Insomnia 发出 POST请求,但是当我们通过前端的 Axios 发出 POST请求时,它会发送一个错误:

has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: It does not have HTTP ok status.

我们对公理的要求是:

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)
});
}

我的行动文件:

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 上所说,它工作得很好,但是当我们提出一个 Axios POST请求时,浏览器控制台上会出现以下内容:

已被 CORS 策略阻塞: 对飞行前请求的响应没有通过访问控制检查: 它没有 HTTP OK 状态。

522605 次浏览

I believe this is the simplest example:

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, Authorization, X-Requested-With")

You can also add a header for Access-Control-Max-Age and of course you can allow any headers and methods that you wish.

Finally you want to respond to the initial request:

if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}

Edit (June 2019): We now use gorilla for this. Their stuff is more actively maintained and they have been doing this for a really long time. Leaving the link to the old one, just in case.

Old Middleware Recommendation below: Of course it would probably be easier to just use middleware for this. I don't think I've used it, but this one seems to come highly recommended.

Enable cross-origin requests in ASP.NET Web API click for more info

Enable CORS in the WebService app. First, add the CORS NuGet package. In Visual Studio, from the Tools menu, select NuGet Package Manager, then select Package Manager Console. In the Package Manager Console window, type the following command:

Install-Package Microsoft.AspNet.WebApi.Cors

This command installs the latest package and updates all dependencies, including the core Web API libraries. Use the -Version flag to target a specific version. The CORS package requires Web API 2.0 or later.

Open the file App_Start/WebApiConfig.cs. Add the following code to the WebApiConfig.Register method:

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 }
);
}
}
}

Next, add the [EnableCors] attribute to your controller/ controller methods

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...
}
}

Enable Cross-Origin Requests (CORS) in ASP.NET Core

The provided solution here is correct. However, the same error can also occur from a user error, where your endpoint request method is NOT matching the method your using when making the request.

For example, the server endpoint is defined with "RequestMethod.PUT" while you are requesting the method as POST.

This answer explains what's going on behind the scenes, and the basics of how to solve this problem in any language. For reference, see the MDN docs on this topic.

You are making a request for a URL from JavaScript running on one domain (say domain-a.com) to an API running on another domain (domain-b.com). When you do that, the browser has to ask domain-b.com if it's okay to allow requests from domain-a.com. It does that with an HTTP OPTIONS request. Then, in the response, the server on domain-b.com has to give (at least) the following HTTP headers that say "Yeah, that's okay":

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

If you're in Chrome, you can see what the response looks like by pressing F12 and going to the "Network" tab to see the response the server on domain-b.com is giving.

So, back to the bare minimum from @threeve's original answer:

header := w.Header()
header.Add("Access-Control-Allow-Origin", "*")


if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}

This will allow anybody from anywhere to access this data. The other headers he's included are necessary for other reasons, but these headers are the bare minimum to get past the CORS (Cross Origin Resource Sharing) requirements.

Angular and Django Rest Framework.

I encountered similar error while making post request to my DRF api. It happened that all I was missing was trailing slash for endpoint.

The only thing that worked for me was creating a new application in the IIS, mapping it to exactly the same physical path, and changing only the authentication to be Anonymous.

The CORS issue should be fixed in the backend. Temporary workaround uses this option.

  1. Open the command prompt

  2. Navigate to chrome installed location OR enter cd "c:\Program Files (x86)\Google\Chrome\Application" OR cd "c:\Program Files\Google\Chrome\Application"

  3. Execute the command chrome.exe --disable-web-security --user-data-dir="c:/ChromeDevSession"

Using the above option, you can able to open new chrome without security. this chrome will not throw any cors issue.

enter image description here

For anyone looking at this and had no result with adding the Access-Control-Allow-Origin try also adding the Access-Control-Allow-Headers. May safe somebody from a headache.

For anyone who haven't find a solution, and if you are using:

  1. AWS HTTP API Gateway;
  2. You are using ANY Method with Authentication for routes and lambda integration;
  3. You believe you have configured the CORS properly;

The error is because the browser is sending a preflight OPTIONS request to your route without Authentication header and thus cannot get CORS headers as response.

To fix this, I added another route for OPTIONS method without Authentication, and the lambda integration simply returns { statusCode: 200 };

In my case it was caused by a silly mistake when copying from other service but in incorrect place (order matters!)

Correct:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());


app.UseRouting();
app.UseStaticFiles();
app.UseCookiePolicy();


app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}

Incorrect:

      public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
app.UseRouting();
app.UseStaticFiles();
app.UseCookiePolicy();


app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});


//had no effect
app.UseCors(x => x
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
}