CORS在golang服务器和JavaScript fetch前端上的应用

huangapple go评论77阅读模式
英文:

CORS on golang server & javascript fetch frontend

问题

我有一个类似以下代码的golang HTTP服务器:

http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
    log.Println("New incoming request")

    // 验证身份
    if u, p, ok := r.BasicAuth(); ok {
        log.Println("Success")
        return
    }
    log.Println("Failed")
})

我从一个部署在端口3000上的JS前端(一个React应用)调用这个HTTP端点,使用以下代码:

fetch('http://localhost:8080/login', {
    method: 'post',
    headers: {
        'Authorization': 'Basic ' + btoa(authHeader),
        'Content-Type': 'application/x-www-form-urlencoded',
        'Access-Control-Allow-Origin': '*'
    },
    body: 'A=1&B=2'
})
.then(function (response) {
    console.log("Authentication Success")
})
.catch(function (err) {
    console.log("Authentication fail", err)
});

上述代码在以下日志中失败。

服务器端日志:

New incoming request
Failed

浏览器开发工具日志:

Fetch API cannot load http://localhost:8080/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

有人可以帮助解决身份验证问题吗?我不确定是否在服务器端遗漏了与CORS相关的内容,或者在客户端进行了错误的身份验证。谢谢。

英文:

I have a golang HTTP server with code like:

	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
	log.Println("New incoming request")

	// Authenticate
	if u, p, ok := r.BasicAuth(); ok {
      log.Println("Success")
      return
    }
    log.Println("Failed")

I call this HTTP endpoint from a JS frontend, a react app deployed on port 3000, using code:

      fetch('http://localhost:8080/login', {
            method: 'post',
            headers: {
                'Authorization': 'Basic ' + btoa(authHeader),
                'Content-Type': 'application/x-www-form-urlencoded',
                'Access-Control-Allow-Origin': '*'
            },
                body: 'A=1&B=2'
            })
            .then(function (response) {
                console.log("Authentication Success")
            })
            .catch(function (err) {
                console.log("Authentication fail", err)
            });

The above code fails with the following logs.

On the server side:

New incoming request
Failed

On the browser, in the developer tools logs:

Fetch API cannot load http://localhost:8080/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 401. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Can someone help fix the authentication problem ? I am not sure if I am missing something related to CORS on the server side or doing bad authentication on the client side. Any help ? Thanks.

答案1

得分: 4

Access-Control-Allow-Origin: * 必须由服务器发送,而不是由客户端发送。假设您正在使用标准的 net/http 处理函数,可以尝试以下代码:

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    if r.Method == "OPTIONS" {
        w.Header().Set("Access-Control-Allow-Headers", "Authorization") // 如果需要,您可以在此处添加更多标头
    } else {
        // 在这里编写您的代码
    }
}

请注意,这是Go语言的示例代码,用于在服务器端设置 Access-Control-Allow-Origin 标头。

英文:

The Access-Control-Allow-Origin: * has to be sent from the server, not by the client. Assuming you are in a standard net/http handler function, try this code:

func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "*")
    if (r.Method == "OPTIONS") {
        w.Header().Set("Access-Control-Allow-Headers", "Authorization") // You can add more headers here if needed
    } else {
        // Your code goes here
    }
}

答案2

得分: 0

首先,在你的处理程序中需要使用模式(schema):

w.Header().Set("Access-Control-Allow-Origin", "*")
if r.Method == "OPTIONS" {
    w.Header().Set("Access-Control-Allow-Headers", "Authorization") // 如果需要,你可以在这里添加更多的头部信息
} else {
    // 在这里编写你的代码
}

但在此之前,你需要在主函数中指定 "OPTIONS":

router.HandleFunc("/your_route/", your_method).Methods("POST", "OPTIONS")

这是因为你的浏览器会发送两个请求 - 第一个是检查是否能够使用某些头部信息(例如 Authorization),然后才会发送数据。

英文:

First - you need to use schema in your handler:

w.Header().Set("Access-Control-Allow-Origin", "*")
    if (r.Method == "OPTIONS") {
        w.Header().Set("Access-Control-Allow-Headers", "Authorization") // You can add more headers here if needed
    } else {
        // Your code goes here
    }

But before it you need to specify in main "OPTIONS":

router.HandleFunc("/your_route/", your_method).Methods("POST", "OPTIONS")

It's because your browser doing 2 request - first to check ability to use some headers (Authorization for example) and next step is posting data

huangapple
  • 本文由 发表于 2016年11月8日 19:04:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/40485248.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定