前往:通过证书与经过身份验证的客户端验证后续的HTTP请求 [英] Go: validate subsequent http requests with authenticated client via certificate

查看:145
本文介绍了前往:通过证书与经过身份验证的客户端验证后续的HTTP请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前正在编写一个HTTP服务器(net/http),该服务器承载多个端点,并且在访问这些端点之前需要客户端身份验证(步骤1).成功通过身份验证后,服务器将发布一个短期令牌,客户端随后将使用该令牌来访问这些端点.当客户端(通过HTTP标头)发送令牌时,在每个处理程序函数的开头都有一段代码,以检查客户端是否已通过身份验证以及所提供的令牌是否有效.我正在寻找一个钩子/包装器,该钩子/包装器可以拦截并验证客户端,而不是从每个终结点函数调用isAuthenticated(r).

func getMyEndpoint(w http.ResponseWriter, r *http.Request) {
        if valid := isAuthenticated(r); !valid {
            w.WriteHeader(http.StatusUnauthorized)
            io.WriteString(w, "Invalid token or Client not authenticated."
            return
        }
        ...
}

func server() {

        http.HandleFunc("/login", clientLoginWithCertAuth)
        http.HandleFunc("/endpoint1", getMyEndpoint)
        http.HandleFunc("/endpoint2", putMyEndpoint)

        server := &http.Server{
                Addr: ":443",
                TLSConfig: &tls.Config{
                        ClientCAs:  caCertPool,
                        ClientAuth: tls.VerifyClientCertIfGiven,
                },
        }

        if err := server.ListenAndServeTLS("cert.pem", "key.pem"); err != nil {
            panic(err)
        }
}

解决方案

您可以创建一个可以包装http.HandlerFunc的函数,例如像这样:

func handleAuth(f http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        if valid := isAuthenticated(r); !valid {
            w.WriteHeader(http.StatusUnauthorized)
            io.WriteString(w, "Invalid token or Client not authenticated.")
            return // this return is *very* important
        }
        // Now call the actual handler, which is authenticated
        f(w, r)
    }
}

现在,您还需要通过将其包装在其他http.HandlerFunc周围(仅那些显然需要身份验证的包装)来注册您的处理程序以使用它:

func server() {
        // No authentication for /login
        http.HandleFunc("/login", clientLoginWithCertAuth)

        // Authentication required
        http.HandleFunc("/endpoint1", handleAuth(getMyEndpoint))
        http.HandleFunc("/endpoint2", handleAuth(putMyEndpoint))

        server := &http.Server{
                Addr: ":443",
                TLSConfig: &tls.Config{
                        ClientCAs:  caCertPool,
                        ClientAuth: tls.VerifyClientCertIfGiven,
                },
        }

        if err := server.ListenAndServeTLS("cert.pem", "key.pem"); err != nil {
            panic(err)
        }
}

这样,只有isAuthenticated为该请求返回true时,处理程序才会被调用(由handleAuth调用),而不会在所有处理程序中重复执行代码.

I'm currently writing a HTTP server(net/http) which hosts multiple endpoints and requires client authentication(step 1) before accessing these endpoints. Upon successful authentication, the server issues a short-lived token which the client then use to access these endpoints. when the client sends the token(via HTTP Header), have a piece of code at the start of every handler function to check the client is authenticated and presented token is valid. I'm looking for a hook/wrapper which can intercept and validate the client instead of calling isAuthenticated(r) from every endpoint function.

func getMyEndpoint(w http.ResponseWriter, r *http.Request) {
        if valid := isAuthenticated(r); !valid {
            w.WriteHeader(http.StatusUnauthorized)
            io.WriteString(w, "Invalid token or Client not authenticated."
            return
        }
        ...
}

func server() {

        http.HandleFunc("/login", clientLoginWithCertAuth)
        http.HandleFunc("/endpoint1", getMyEndpoint)
        http.HandleFunc("/endpoint2", putMyEndpoint)

        server := &http.Server{
                Addr: ":443",
                TLSConfig: &tls.Config{
                        ClientCAs:  caCertPool,
                        ClientAuth: tls.VerifyClientCertIfGiven,
                },
        }

        if err := server.ListenAndServeTLS("cert.pem", "key.pem"); err != nil {
            panic(err)
        }
}

解决方案

You can create a function that can wrap a http.HandlerFunc, e.g. like this:

func handleAuth(f http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        if valid := isAuthenticated(r); !valid {
            w.WriteHeader(http.StatusUnauthorized)
            io.WriteString(w, "Invalid token or Client not authenticated.")
            return // this return is *very* important
        }
        // Now call the actual handler, which is authenticated
        f(w, r)
    }
}

Now you also need to register your handlers to use it by wrapping it around your other http.HandlerFuncs (only those that need authentication obviously):

func server() {
        // No authentication for /login
        http.HandleFunc("/login", clientLoginWithCertAuth)

        // Authentication required
        http.HandleFunc("/endpoint1", handleAuth(getMyEndpoint))
        http.HandleFunc("/endpoint2", handleAuth(putMyEndpoint))

        server := &http.Server{
                Addr: ":443",
                TLSConfig: &tls.Config{
                        ClientCAs:  caCertPool,
                        ClientAuth: tls.VerifyClientCertIfGiven,
                },
        }

        if err := server.ListenAndServeTLS("cert.pem", "key.pem"); err != nil {
            panic(err)
        }
}

That way, your handlers only get called (by handleAuth) if isAuthenticated returns true for that request, without duplicating the code in all of them.

这篇关于前往:通过证书与经过身份验证的客户端验证后续的HTTP请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆