dongliang2058 2018-10-19 09:21
浏览 126

当前端和API都在同一Go服务器上时,如何从CSRF保护REST API?

I am working on a web site created in Go.

It is possible to access it both via web (server side pages generated via golang templates) and a REST API (for external users who whant to integrate their own software). The Go server handles both types of requests, with a subrouter that handles the API when calls are sent to the subpath "my-url-root/api".

  • The web pages use secure cookies
  • The API is stateless: no cookies (each API method must receive in the header an authentication token obtained via a dedicated login method)

I successfully applied gorilla/csrf to protect the web pages from csrf attacks, but that modification (essential before I go live) is now creating an issue with the API.

My question When the CSRF is implemented, all GET requests sent to the api URLs work as expected, but any other request sent (e.g. a POST to a method to add something via my REST api) generates an html response that typically states "forbidden - invalid csrf token".

Is there a straightforward way that I am missing? I searched for answers but none applicable to the case where the api is served by the same server and most of all it is stateless. Should I see if I can "disable" the gorilla csrf protection for the subrouter (though I do not even know if that is possible and if that is even safe...)?

Thanks for your help.

  • 写回答

1条回答 默认 最新

  • dsrbb20862 2018-10-24 20:04
    关注

    Ok, so I tried to apply the suggestions above and I came up with a solution to my problem.

    I tested that it works by checking web and api calls against my urls and sub-urls with and without the csrf protection.

    Just a clarification to my previous comment. To be more precise the order I created the Submuxes did not matter but of course I had then followed a proper order when I wrote down the lines to Handle each path.

    So, the order IS important.

    This is what I did (just bits of code).

    I used goji as a router and gorilla/csrf for the csrf protection.

    NOTE: I did not include all my code but just the most important parts to describe what I did.

    1) I created a mux using

    mux := goji.NewMux()
    

    2) since my APIs are served under the url "/api" and related sub urls, I created a Submux for the api

    apiMux := goji.SubMux()
    

    3) I assigned the pages that match the path "/api" and "/api*" to this subMux

    Note that I did NOT include any csrf protection

    mux.Handle(pat.New("/api/*"), apiMux)
    
    mux.Handle(pat.New("/api"), apiMux)
    

    4) I created a Submux for web pages of my site

    webMux := goji.SubMux()
    

    5) I assigned the pages that match the path "/" and "/*" to this subMux

    Note that here in my code I linked the middleware for the csrf protection

    mux.Handle(pat.New("/"), csrf.Protect(csrfKey, csrf.Secure(true))(webMux))
    mux.Handle(pat.New("/*"), csrf.Protect(csrfKey, csrf.Secure(true))(webMux))
    

    6) For my benefit, I created other SubMuxes to handle other paths, like "/users", "/users/1", "/users/addform". This step is important: I assigned this "userMux" to the webMux, and not to the main mux created at step 1.

    In this way, the csrf protection is inherited. Example:

    usersMux := goji.SubMux()
    
    webMux.Handle(pat.New("/users/*"), usersMux)
    
    webMux.Handle(pat.New("/users"), usersMux)
    

    IN few words, this was the solution to my problem:

    I) I assigned this "apiMux" to the main mux created at step 1.

    I did not assigned it to any other mux. I did NOT assigned it to the webMux that handles the root url "/" and "/*"

    II) The order is important, so I implemented the code for the API urls and then the code for the web urls

    I hope it helps. And most of all I hope the explanation was clear... (if not just let me know). Thanks for pointing me in the right direction

    评论

报告相同问题?

悬赏问题

  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值
  • ¥15 我想咨询一下路面纹理三维点云数据处理的一些问题,上传的坐标文件里是怎么对无序点进行编号的,以及xy坐标在处理的时候是进行整体模型分片处理的吗
  • ¥15 CSAPPattacklab
  • ¥15 一直显示正在等待HID—ISP
  • ¥15 Python turtle 画图
  • ¥15 关于大棚监测的pcb板设计
  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用