【问题标题】:Go: validate subsequent http requests with authenticated client via certificateGo:通过证书使用经过身份验证的客户端验证后续的 http 请求
【发布时间】:2020-07-11 16:18:41
【问题描述】:

我目前正在编写一个 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)
        }
}

【问题讨论】:

  • “我正在寻找一个钩子/包装器,它可以拦截和验证客户端,而不是从每个端点函数调用 isAuthenticated(r)。”那是什么意思?如果不是通过调用 isAuthenticated,钩子将如何验证客户端?或者您是在问如何编写一个 http.HandlerFunc 作为这样的包装器?
  • 我猜这就是 OP 的要求。

标签: http go ssl ssl-client-authentication


【解决方案1】:

您可以创建一个可以包装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.HandlerFuncs 周围(仅那些显然需要身份验证的人):

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),而不会在所有处理程序中复制代码。

【讨论】:

  • 非常感谢您的帮助。它对我有用。
猜你喜欢
  • 1970-01-01
  • 2015-02-26
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 2011-05-20
  • 1970-01-01
相关资源
最近更新 更多