英文:
HTTP 400 When Using Nosurf and Appengine Blobstore
问题
我正在使用Appengine Blob存储示例,它工作得很好(我修改了以接受两个文件,但这不是问题所在)。然而,当我打开nosurf时,它给我返回一个HTTP 400
错误。我已经将csrf令牌传递给我的表单。即使我只上传一个文件,问题仍然存在。
nosurf
对于其他表单工作得很好,但在blobstore文件上传时给我带来了麻烦。
由于代码很长(只是示例代码进行了一些小的修改),我将其放在这里:http://play.golang.org/p/SJADmn-WvJ(当然你不能在那里运行它,因为你需要app-engine和nosurf)
代码的一小部分:
const rootTemplateHTML = `
<html><body>
<form action="{{.UpUrl}}" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file1"><br>
Upload File: <input type="file" name="file2"><br>
<input type="hidden" name="csrf_token" value="{{ .Token }}">
<input type="submit" name="submit" value="Submit">
</form>
</body></html>
`
这段代码不起作用:
http.Handle("/", nosurf.New(http.HandlerFunc(handleRoot)))
http.Handle("/upload", nosurf.New(http.HandlerFunc(handleUpload)))
http.HandleFunc("/serve/", handleServe)
但这段代码起作用(没有400
状态):
http.HandleFunc("/", handleRoot)
http.HandleFunc("/serve/", handleServe)
http.HandleFunc("/upload", handleUpload)
这是与nosurf
还是app-engine
有关的问题吗?对于如何解决这个问题,有什么建议吗?
谢谢!
英文:
I am using the Appengine Blob store example and it works fine (I modified to take two files but that is not the issue). However, when I turn on nosurf it gives me a HTTP 400
. I am passing in the csrf token to my form. The issue exists even if I just upload one file.
nosurf
works just fine for other forms but only gives me trouble with blobstore file upload.
Since the code is large (it is the just the example with some minor tweaks), I have put it here: http://play.golang.org/p/SJADmn-WvJ (of course you cannot run it there as you need app-engine and nosurf)
Small parts of the code:
const rootTemplateHTML = `
<html><body>
<form action="{{.UpUrl}}" method="POST" enctype="multipart/form-data">
Upload File: <input type="file" name="file1"><br>
Upload File: <input type="file" name="file2"><br>
<input type="hidden" name="csrf_token" value="{{ .Token }}">
<input type="submit" name="submit" value="Submit">
</form>
</body></html>
`
This does not work:
http.Handle("/", nosurf.New(http.HandlerFunc(handleRoot)))
http.Handle("/upload", nosurf.New(http.HandlerFunc(handleUpload)))
http.HandleFunc("/serve/", handleServe)
But this works (no 400
status):
http.HandleFunc("/", handleRoot)
http.HandleFunc("/serve/", handleServe)
http.HandleFunc("/upload", handleUpload)
Is this something to do with nosurf
or app-engine
? Any suggestions on what I should do to fix this issue?
Thanks!
答案1
得分: 1
Blobstore上传URL的工作原理是将文件上传实际上发送到应用程序上的一个特殊的/_ah/...
路由,该路由实际上不由应用程序处理,而是用作基础设施将数据发送到存储上传处理程序的信号,存储上传处理程序是一个内部处理程序,用于实际将数据放入存储中。
您传递给生成上传URL的函数的回调路由是您的应用程序上将在完成上传后接收到一个请求的路由,该请求包含的不是文件数据,而是文件的元数据,例如文件名,以及传递给请求的任何其他参数(例如,重要的是CSRF令牌)。
但是,您传递的令牌是通过调用nosurf.Token(r)
生成的,其中r
是用户浏览器在生成页面时向您的应用程序发出的请求。当存储上传处理程序将回调请求发送到您的/upload
路由时,nosurf期望发送请求的客户端(存储上传处理程序)具有为该客户端(存储上传处理程序)生成的有效CSRF令牌,并根据该期望验证该请求。但是,它收到的是为最初发送给用户的包含表单的页面生成的CSRF令牌。
英文:
The blobstore upload URL works by actually posting your file upload to a special /_ah/...
route on your app, which is not actually handled by your app but is used as a signal for the infrastructure to send the data over to the storage upload handler, which is an internal handler that does the actual put to storage.
The callback route you pass to the function that generated the upload URL is the route on your app which will receive a request once this is done that contains not the file data but the file metadata, such as the filenames, along with any other parameters passed to the request (such as, importantly, the CSRF token).
The token which you pass, however, was generated from a call to nosurf.Token(r)
, where r
is the request the user's browser made to your app at the time the page was generated. When the storage upload handler sends the callback request to your /upload
route, nosurf expects the client that sent the request to have a valid CSRF token generated for that client (the storage upload handler) and validates that request based on that expectation. Instead it receives the CSRF token that was generated for the page which you originally sent to the user, containing the form.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论