在下载之前验证请求。

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

Validate request before downloading

问题

我正在尝试创建一个Web服务,用于发送和接收大文件,作为远程备份存储解决方案的一部分。

当Web服务器接收到请求时,需要对其进行身份验证,然后再存储数据。

目前,我正在考虑将身份验证方法发送到请求头中,将实际内容发送到请求体中,这是相当标准的做法。

然而,由于请求体的大小,我想知道是否有可能在完全接收请求体之前对请求头进行身份验证,并在请求无法验证时立即响应或断开连接?

我还没有开始实施,但我倾向于使用Golang进行实现。在其前面将有一个nginx服务器,如果有任何区别的话。

编辑:

也许我在原问题中没有表达清楚,但主要关注点应该是:
在接收完整有效载荷之前,是否有可能确定请求是否经过身份验证,并在不符合条件的情况下立即断开连接或响应?

就像...是否可能将请求解释为流,可以仅对第一部分进行操作,即使其余的有效载荷尚未到达。

对于造成的困惑,我表示抱歉。

英文:

I am trying to create a webservice which will send and receive large files, as part of a storage solution for remote backups.

When a request is received by the webserver it needs to be authenticated before it stores the data.

At the moment I'm considering sending sending authentication methods in the headers and the actual content in the body. Fairly standard.

However I would like to know, due to the size of the body, if it is possible to authenticate the headers, and possibly respond to the request/drop the connection before completely receiving the body, if the request cannot be validated?

I haven't started implementing yet, but I am leaning towards an implementation using Golang. There will be an nginx server in front of it, in case it makes any difference.

Edit:

Maybe I haven't been clear enough, in my original question, but the main focus should be:
Is it possible to figure out if a request is authenticated before receiving the entire payload and possibly drop the connection/respond if that is not the case?

Like.. Is it possible to interpret the request as a stream, where you can act on just the first part, even though the rest of the payload hasn't arrived yet.

Sorry for the confusion.

答案1

得分: 0

我想知道,由于请求体的大小,是否可以在完全接收请求体之前对标头进行身份验证,并在请求无法验证时可能回应请求/断开连接?

身份验证的工作方式如下:在获取请求的URL之前,您先验证用户身份。

您可以通过任何身份验证中间件来实现,例如:

有关身份验证的更多选择,请参阅《用于 Go Web 应用程序的终端用户身份验证》。

英文:

> I would like to know, due to the size of the body, if it is possible to authenticate the headers, and possibly respond to the request/drop the connection before completely receiving the body, if the request cannot be validated?

This is how authentication work: you validate the user before getting the requested url.

You do it through any auth middleware like:

More on the authentication alternatives in "End-user authentication for Go web applications".

答案2

得分: 0

大多数情况下,你可以使用Gorilla的sessions包来处理会话。但是你也可以使用"net/http"包来实现。在这个例子中,有两个文件,一个是main.go,另一个是public文件夹下的index.html。

服务器端(main.go)##

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/get/token", getTokenHandler)
    r.HandleFunc("/send/token", sendTokenHandler)
    r.PathPrefix("/").Handler(http.FileServer(http.Dir("./public/")))
    http.Handle("/", r)
    log.Println("Listening...")
    http.ListenAndServe(":3000", nil)
}

func getTokenHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("secret-token", "abcd")
    fmt.Fprint(w, "abcd")
}

func sendTokenHandler(w http.ResponseWriter, r *http.Request) {
    mySecret := r.Header.Get("secret-token")
    if mySecret != "abcd" {
        w.Header().Add("response-to-token", "false")
        fmt.Fprint(w, "you are not allowed")
    } else {
        w.Header().Add("response-to-token", "true")
        fmt.Fprint(w, "you are allowed")
    }
}

在客户端的JavaScript中,你可以使用一个函数来获取头部信息。

客户端(public/index.html)##

<html>
    <head>
        <meta charset="utf-8">
        <title>Upload</title>
        <script type="text/javascript">

            var getSecret = function (){
                var req = new XMLHttpRequest();
                req.open('GET', "get/token", false);
                req.send();
                var secretToken = req.getResponseHeader("secret-token");
                document.getElementById('secretInput').value = secretToken;
            }

            var postSecret = function(){
                var secret = document.getElementById('secretInput').value;
                var req = new XMLHttpRequest();
                req.open('POST', "send/token", false);
                req.setRequestHeader("secret-token", secret);
                req.send();
                var responseToken = req.getResponseHeader("response-to-token");
                console.log(responseToken);
            }
            </script>
        </head>
        <body>
            <button onclick="getSecret()">获取密钥</button>
            <hr>
            <input id="secretInput" type="text"></input>
            <button onclick="postSecret()">提交密钥</button>
        </body>
</html>

最后,如果你的文件非常大,你可能希望将其分割成多个部分,这样如果令牌不正确,你可以发送一条消息。对于文件分割部分,你可以使用JavaScript。我在stackoverflow上找到了一个JavaScript的解决方案:链接

英文:

Most of the time you would use a session with the great package sessions from Gorilla.
But you could make it without with the "het/http" package.
in this exemple there is tow files main.go and index.html into the public folder

##Server side in go (main.go)##

package main

import (
    &quot;fmt&quot;
    &quot;github.com/gorilla/mux&quot;
    &quot;log&quot;
    &quot;net/http&quot;
)
    
func main() {
    r := mux.NewRouter()
    r.HandleFunc(&quot;/get/token&quot;, getTokenHandler)
    r.HandleFunc(&quot;/send/token&quot;, sendTokenHandler)
    r.PathPrefix(&quot;/&quot;).Handler(http.FileServer(http.Dir(&quot;./public/&quot;)))
    http.Handle(&quot;/&quot;, r)
    log.Println(&quot;Listening...&quot;)
    http.ListenAndServe(&quot;:3000&quot;, nil)
}
    
func getTokenHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Add(&quot;secret-token&quot;, &quot;abcd&quot;)
    fmt.Fprint(w, &quot;abcd&quot;)
}
    
func sendTokenHandler(w http.ResponseWriter, r *http.Request) {
    mySecret := r.Header.Get(&quot;secret-token&quot;)
    if mySecret != &quot;abcd&quot; {
        w.Header().Add(&quot;response-to-token&quot;, &quot;false&quot;)
        fmt.Fprint(w, &quot;you are not allowed&quot;)
    } else {
        w.Header().Add(&quot;response-to-token&quot;, &quot;true&quot;)
        fmt.Fprint(w, &quot;you are allowed&quot;)
    }
}

On the client side in javascript you may use a function to get the header infos like
##Client side with JS (public/index.html)##

&lt;html&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;title&gt;Upload&lt;/title&gt;
        &lt;script type=&quot;text/javascript&quot;&gt;

            var getSecret = function (){
                var req = new XMLHttpRequest();
                req.open(&#39;GET&#39;, &quot;get/token&quot;, false);
                req.send();
                var secretToken = req.getResponseHeader(&quot;secret-token&quot;);
                document.getElementById(&#39;secretInput&#39;).value = secretToken;
            }

            var postSecret = function(){
                var secret = document.getElementById(&#39;secretInput&#39;).value;
                var req = new XMLHttpRequest();
                req.open(&#39;POST&#39;, &quot;send/token&quot;, false);
                req.setRequestHeader(&quot;secret-token&quot;, secret);
                req.send();
                var responseToken = req.getResponseHeader(&quot;response-to-token&quot;);
                console.log(responseToken);
            }
            &lt;/script&gt;
        &lt;/head&gt;
        &lt;body&gt;
            &lt;button onclick=&quot;getSecret()&quot; &gt;get Secret&lt;/button&gt;
            &lt;hr&gt;
            &lt;input id=&quot;secretInput&quot; type=&quot;text&quot;&gt;&lt;/input&gt;
            &lt;button onclick=&quot;postSecret()&quot;&gt;post Secret&lt;/button&gt;
        &lt;/body&gt;
&lt;/html&gt;

##finally split your file##
If your file is verry big you may want ton split it in parts so you could send a message if the token is not right. For the splitting part you can use Javascript. I've just found a solution in js on stackoverflow

答案3

得分: 0

如果您将文件作为请求主体发布,您可以使用身份验证标头进行验证,而无需等待文件完全上传。

然后,您可以使用io.Copy将请求主体复制到文件中。

_, err := io.Copy(someFile, req.Body)

如果您使用'multipart/form-data',则http包将妨碍您的操作。将文件作为请求主体发布将使您能够将请求主体的内容作为流访问,并且io.Copy将以合理的方式管理文件的复制。

英文:

If you post the file as the body of your request you can use an auth header to validate without waiting for the file to fully upload.

You can then use io.Copy to copy from the request body to a file.

_, err := io.Copy(someFile, req.Body)

Don't use 'multipart/form-data' the http pkg will get in your way if you do. Posting the file as the body will let you access the contents of the request body as a stream and io.Copy will manage the copy to the file in a sensible way.

huangapple
  • 本文由 发表于 2014年9月2日 15:16:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/25617831.html
匿名

发表评论

匿名网友

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

确定