使用Gin框架时能否让GET请求无需MTLS校验其余请求启用MTLS防护
基于Gin实现路由组级别的mTLS校验方案
TLS握手逻辑发生在HTTP请求路由匹配之前,因此无法直接为不同Gin路由组绑定独立的TLS配置。我们可以通过调整服务端TLS策略+自定义中间件的方式实现需求:先将服务端配置为「请求但不强制校验客户端证书」,再通过Gin中间件仅对需要防护的路由组做mTLS校验。
具体实现步骤
- 调整HTTP服务的TLS配置,将
ClientAuth字段设置为tls.RequestClientCert,服务端会主动请求客户端证书,但不会直接拒绝未携带证书的请求 - 实现mTLS校验中间件,逻辑为校验请求携带的客户端证书是否被信任的CA根证书池认可,校验不通过直接返回错误响应
- 将校验中间件挂载到需要mTLS保护的私有路由组,公开路由组无需挂载该中间件
修改后的完整代码
package main import ( "crypto/tls" "crypto/x509" "errors" "fmt" "io/ioutil" "net/http" "log" "github.com/gin-gonic/gin" ) // mTLS校验中间件 func mtlsAuthMiddleware(rootCAs *x509.CertPool) gin.HandlerFunc { return func(c *gin.Context) { // 检查是否携带客户端证书 if len(c.Request.TLS.PeerCertificates) == 0 { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "需提供客户端证书"}) return } // 校验客户端证书有效性 clientCert := c.Request.TLS.PeerCertificates[0] verifyOpts := x509.VerifyOptions{ Roots: rootCAs, } if _, err := clientCert.Verify(verifyOpts); err != nil { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "客户端证书无效"}) return } c.Next() } } func main() { router := gin.Default() // 无需mTLS校验的公开路由组 public := router.Group("/") // 需要mTLS校验的私有路由组 private := router.Group("/") public.GET("/insecure-ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "insecure pong", }) }) private.POST("/secure-ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "secure pong", }) }) // 初始化信任的CA根证书池 rootCAs, err := x509.SystemCertPool() if err != nil { log.Fatal(err) } if rootCAs == nil { rootCAs = x509.NewCertPool() } caCert, err := ioutil.ReadFile("cacert.pem") if err != nil { log.Fatal(err) } if ok := rootCAs.AppendCertsFromPEM(caCert); !ok { err := errors.New("添加CA证书到系统信任池失败") log.Fatal(err) } // 私有路由组挂载mTLS校验中间件 private.Use(mtlsAuthMiddleware(rootCAs)) server := http.Server{ Addr: fmt.Sprintf(":%v", 8080), Handler: router, TLSConfig: &tls.Config{ RootCAs: rootCAs, ClientAuth: tls.RequestClientCert, // 关键配置:请求但不强制校验客户端证书 }, } err = server.ListenAndServeTLS("certificate.crt", "privateKey.key") if err != nil { log.Fatal(err) } }
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

