最新公告
  • 欢迎您光临码农资源网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!加入我们
  • CORS 策略:对预检请求的响应未通过访问控制检查:无“Access-Control-Allow-Origin”

    cors 策略:对预检请求的响应未通过访问控制检查:无“access-control-allow-origin”

    问题内容

    我在后端使用 golang 和 gin-gonic/gin web 框架,在前端使用 react axios。我已经尝试解决它两天了,但我仍然遇到以下相同的错误:

    cors policy: response to preflight request doesn't pass access control check: no 'access-control-allow-origin' header is present on the requested resource.

    仅当我尝试发送 patch 请求时才会发生此错误,因此该请求需要预检 options 请求,但 get 和 post 一切都按预期工作,它们不运行任何预检检查。

    这是我的路由器配置的代码:

    package main
    
    import (
        "book_renting/api"
        "log"
        "net/http"
    
        "github.com/gin-contrib/sessions"
        "github.com/gin-contrib/sessions/cookie"
        "github.com/gin-gonic/contrib/cors"
        "github.com/gin-gonic/gin"
        _ "github.com/lib/pq"
    )
    
    func main() {
    
        router := gin.default()
        store := cookie.newstore([]byte("your-secret-key"))
        store.options(sessions.options{maxage: 60 * 60 * 24})
    
        router.use(cors.default())
        router.use(sessions.sessions("sessions", store))
    
        router.use(func(c *gin.context) {
            host := c.request.header.get("origin")
            c.writer.header().set("access-control-allow-origin", host)
            c.writer.header().set("access-control-allow-credentials", "true")
            c.writer.header().set("access-control-allow-headers", "content-type, authorization")
            c.writer.header().set("access-control-allow-methods", "get, post, put, delete, patch, options")
            if c.request.method == "options" {
                log.println("handling options request")
                c.abortwithstatus(http.statusnocontent)
                return
            }
            log.println("executing cors middleware")
            c.next()
        })
    
        router.post("/login", api.handlelogin)
        router.get("/logout", api.handlelogout)
        router.post("/register", api.handleregister)
        router.get("/getcookie", api.getcookiesession)
    
        router.get("/books", api.getbooksapi)
        router.get("/books/:id", api.bookbyidapi)
        router.patch("/rent/:id", api.rentbookapi)
        router.patch("/return/:id", api.returnbookapi)
        router.run("localhost:3000")
    }

    这是前端:

    import axios from 'axios'
    
    const url = 'http://localhost:3000'
    
    export const loginuser = async (credentials) => await axios.post(`${url}/login`, credentials, {withcredentials: true})
    export const logoutuser = async () => await axios.get(`${url}/logout`, {withcredentials: true})
    export const registeruser = () => axios.post(`${url}/register`)
    export const fetchbooks = () => axios.get(`${url}/books`, { withcredentials: true })
    export const fetchbookbyid = (book_id) => axios.get(`${url}/books/${book_id}`, { withcredentials: true })
    export const rentbook = (book_id) => axios.patch(`${url}/rent/${book_id}`, { withcredentials: true })
    export const returnbook = (book_id) => axios.patch(`${url}/return/${book_id}`, { withcredentials: true })

    我非常确定我正确设置了后端,它应该返回所有必要的标头。

    例如,对于 get 请求,响应标头如下所示:

    http/1.1 200 ok
    access-control-allow-credentials: true
    access-control-allow-headers: content-type, authorization
    access-control-allow-methods: get, post, put, delete, patch, options
    access-control-allow-origin: http://localhost:3001
    content-type: application/json; charset=utf-8
    date: sat, 10 jun 2023 22:12:11 gmt
    content-length: 495

    虽然对于 patch 请求尝试,我没有任何响应(毫不奇怪),并且预检响应标头是:

    http/1.1 200 ok
    date: sat, 10 jun 2023 22:12:12 gmt
    content-length: 0

    您对可能出现的问题有什么建议吗?经过这两天我已经毫无头绪了。预先感谢您!

    我还尝试添加标题:

    c.writer.header().set("access-control-allow-origin", host)
            c.writer.header().set("access-control-allow-credentials", "true")
            c.writer.header().set("access-control-allow-headers", "content-type, authorization")
            c.writer.header().set("access-control-allow-methods", "get, post, put, delete, patch, options")

    …再次在 if 语句中:

    if c.request.method == "options" {
        log.println("handling options request")
        c.abortwithstatus(http.statusnocontent)
        return
        }

    但这根本没有帮助。事实上,这个if语句在执行预检时并没有执行,我从控制台知道服务器正在执行options请求。

    [gin] 2023/06/11 - 00:12:13 | 200 |       7.708µs |       127.0.0.1 | options  "/rent/2"

    编辑:

    这是发送 patch 请求的 curl 命令(因此实际上这是预检 options 请求):

    curl 'http://localhost:3000/return/2' 
      -x 'options' 
      -h 'accept: */*' 
      -h 'accept-language: en-us,en;q=0.9,pl-pl;q=0.8,pl;q=0.7' 
      -h 'access-control-request-headers: content-type' 
      -h 'access-control-request-method: patch' 
      -h 'cache-control: no-cache' 
      -h 'connection: keep-alive' 
      -h 'origin: http://localhost:3001' 
      -h 'pragma: no-cache' 
      -h 'referer: http://localhost:3001/' 
      -h 'sec-fetch-dest: empty' 
      -h 'sec-fetch-mode: cors' 
      -h 'sec-fetch-site: same-site' 
      -h 'user-agent: mozilla/5.0 (macintosh; intel mac os x 10_15_7) applewebkit/537.36 (khtml, like gecko) chrome/114.0.0.0 safari/537.36' 
      --compressed

    对此请求的响应:

    HTTP/1.1 200 OK
    Date: Sun, 11 Jun 2023 01:22:57 GMT
    Content-Length: 0

    正确答案

    事实证明,您正在使用已弃用的软件包 github.com/gin-gonic/contrib/cors。您应该使用 github.com/gin-contrib/cors 代替。这是使用 github.com/gin-contrib/cors 的演示配置:

    package main
    
    import (
        "github.com/gin-contrib/cors"
        "github.com/gin-contrib/sessions"
        "github.com/gin-contrib/sessions/cookie"
        "github.com/gin-gonic/gin"
    )
    
    func main() {
        router := gin.default()
    
        config := cors.defaultconfig()
        config.addallowheaders("authorization")
        config.allowcredentials = true
        config.allowallorigins = false
        // i think you should whitelist a limited origins instead:
        //  config.allowallorigins = []{"xxxx", "xxxx"}
        config.alloworiginfunc = func(origin string) bool {
            return true
        }
        router.use(cors.new(config))
    
        store := cookie.newstore([]byte("your-secret-key"))
        store.options(sessions.options{maxage: 60 * 60 * 24})
        router.use(sessions.sessions("sessions", store))
    
        // routes below
    
        router.run("localhost:3000")
    }
    

    由于某种原因,patch 请求标头缺少“cookie”标头,尽管我使用了 withcredentials 参数。

    axios.patch(`${url}/rent/${book_id}`, { withcredentials: true })
    

    这里 { withcredentials: true } 被视为数据,并且没有配置。如果你没有数据发送到服务器,你应该这样写:

    axios.patch(`${url}/rent/${book_id}`, null, { withCredentials: true })
    
    想要了解更多内容,请持续关注码农资源网,一起探索发现编程世界的无限可能!
    本站部分资源来源于网络,仅限用于学习和研究目的,请勿用于其他用途。
    如有侵权请发送邮件至1943759704@qq.com删除

    码农资源网 » CORS 策略:对预检请求的响应未通过访问控制检查:无“Access-Control-Allow-Origin”
    • 7会员总数(位)
    • 25846资源总数(个)
    • 0本周发布(个)
    • 0 今日发布(个)
    • 293稳定运行(天)

    提供最优质的资源集合

    立即查看 了解详情