douxun1407 2018-11-12 22:51
浏览 235
已采纳

在JSON API调用上禁用CSRF

I have a website project. It uses Go and the Gorilla and it's CSRF packages to protect against CSRF. I also have a JSON API that authenticates using a JWT like token provider (internal), so a user must authenticate with that before issuing a JSON request each time. So the CSRF is not an issue on the JSON side. At least I don't think so.

Here's my code, where I am using a NewRouter for web Paths, and a Subrouter for the /api/v1/[endpoint]s. If I call a JSON endpoint that does a POST, the CSRF is engaged and I get a Forbidden - CSRF token invalid. I was under the assume, that perhaps a Sub Router would not have the middleware for the CSRF check associated with.

router := mux.NewRouter().StrictSlash(false)
router.Path("/").HandlerFunc(myApp.IndexHandler).Methods("GET")

apiRouter := router.PathPrefix("/api").Subrouter()
apiRouter.Path("/dosomething").HandlerFunc(myApp.DoSomethingAPIHandler).Methods("POST", "OPTIONS")

http.ListenAndServe(":8000",
    csrf.Protect(
        []byte("my-long-key-here-redacted"),
        csrf.Secure(false), // Set to false as we offload SSL elsewhere
    )(router)))

Question: How do I get my API to work with or without CSRF protection? Obviously, the web paths will need to be protected to protect form posts.

  • 写回答

1条回答 默认 最新

  • dtcyv3985 2018-11-12 23:55
    关注

    One option is to only use the CSRF protection on specific HTTP handlers, rather than protecting the entire router. Note that this will require you to perform a type conversion on your myApp.IndexHandler in order to satisfy the type signature for the function returned by csrf.Protect().

    router := mux.NewRouter().StrictSlash(false)
    
    // Instead of protecting your entire router, you can protect specific HTTP
    // handlers.
    router.Path("/").Handler(
        csrf.Protect(
            []byte("my-long-key-here-redacted"),
            csrf.Secure(false),
        )(http.HandlerFunc(myApp.IndexHandler)),
    ).Methods("GET")
    
    apiRouter := router.PathPrefix("/api").Subrouter()
    apiRouter.Path("/dosomething").HandlerFunc(myApp.DoSomethingAPIHandler).Methods("POST", "OPTIONS")
    
    http.ListenAndServe(
        ":8000",
        router,
    )
    

    Alternatively, you can use the function returned from csrf.Protect() to create your own middleware, with logic to only add the CSRF protection on certain requests. You could use this approach to only add protection on endpoints with the prefix /api for example, as I've done in the code below.

    protectionMiddleware := func(handler http.Handler) http.Handler {
        protectionFn := csrf.Protect(
            []byte("my-long-key-here-redacted"),
            csrf.Secure(false),
        )
    
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            // Use some kind of condition here to see if the router should use
            // the CSRF protection. For the sake of this example, we'll check
            // the path prefix.
            if !strings.HasPrefix(r.URL.Path, "/api") {
                protectionFn(handler).ServeHTTP(w, r)
                return
            }
    
            handler.ServeHTTP(w, r)
        })
    }
    
    router := mux.NewRouter().StrictSlash(false)
    router.Path("/").HandlerFunc(myApp.IndexHandler).Methods("GET")
    
    apiRouter := router.PathPrefix("/api").Subrouter()
    apiRouter.Path("/dosomething").HandlerFunc(myApp.DoSomethingAPIHandler).Methods("POST", "OPTIONS")
    
    http.ListenAndServe(
        ":8000",
        protectionMiddleware(router),
    )
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)
  • ¥15 keil里为什么main.c定义的函数在it.c调用不了
  • ¥50 切换TabTip键盘的输入法