Golang中间件使用问题求助
Golang中间件使用问题求助 大家好,我在理解中间件的工作原理时遇到了困难。
我正在尝试使用这个SAML认证包(https://github.com/crewjam/saml)来实现一个与基于SAML的单点登录配合的Web应用“服务提供者”。这个中间件工作得很好,但我需要在代码中对其进行一些修改,以覆盖其工作方式。
我需要做的是,在我的代码中创建一个处理程序来替换samlsp/middleware.go中的这个函数:
func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == m.ServiceProvider.MetadataURL.Path {
m.ServeMetadata(w, r)
return
}
if r.URL.Path == m.ServiceProvider.AcsURL.Path {
m.ServeACS(w, r)
return
}
http.NotFoundHandler().ServeHTTP(w, r)
}
我想把它替换成……
func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/metadata" {
m.ServeMetadata(w, r)
return
}
if r.URL.Path == "/acs" {
m.ServeACS(w, r)
return
}
http.NotFoundHandler().ServeHTTP(w, r)
}
到这里我就有点困惑了,我不明白为什么我不能从我自己的代码中调用ServeACS和ServeMetadata函数,比如使用类似samlsp.ServeACS的方式。
我想我可能对中间件和接口之间的关系有点混淆,这两个概念相对于我相当基础的编程经验来说都比较高级。我希望有人能好心提供一个示例,说明如何在我自己的代码中覆盖这个功能。
谢谢
更多关于Golang中间件使用问题求助的实战教程也可以访问 https://www.itying.com/category-94-b0.html
或许你可以尝试创建自己的中间件结构体,并将其嵌入到SAML中间件结构体中。这样,你的自定义中间件就能访问(“继承”)SAML中间件的方法和字段。然后,你可以用自己的实现来重写SAML中间件的ServeHTTP方法。
type MyMiddleware struct {
*saml.Middleware
}
func (m *MyMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/metadata" {
m.ServeMetadata(w, r)
return
}
if r.URL.Path == "/acs" {
m.ServeACS(w, r)
return
}
http.NotFoundHandler().ServeHTTP(w, r)
}
samlSP, _ := samlsp.New(samlsp.Options{
// 构建中间件所需的任何选项
})
m := &MyMiddleware{samlSP}
http.Handle("/saml/", m)
更多关于Golang中间件使用问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
再次感谢,我之前尝试过类似的方法,但遇到了错误……
m.ServeMetadata 未定义(类型 *MyMiddleware 没有字段或方法 ServeMetadata)编译器[MissingFieldOrMethod]。
结果发现我犯了一个愚蠢的错误,我使用的是该库的 4.5 发布版本,而其中的方法尚未从 serveMetadata 和 serveACS 更改为 ServeMetadata 和 ServeACS。我原本以为是我理解错了,但你提供的这个例子表明,我已经尝试过一个本应奏效的类似解决方案,但它没有成功。这促使我去尝试找出它不工作的原因,然后我才意识到方法名称的更改尚未实现!
现在我为这样一个愚蠢的疏忽感到有点尴尬,但非常感谢你为帮助我排查问题所做的所有努力。能有其他人提供一些见解非常有帮助,独自进行项目时,遇到问题无人可问会非常困难。非常感谢你的帮助,非常感谢你抽出时间。
在此期间,我创建了自己的小型中间件,它接收 http.Request,从路径中移除 /saml,然后返回修改后的请求的 ServeHTTP。等库更新后我会再重新审视它。
我认为你实际上并不需要替换该函数。 ServiceProvider.MetadataURL 和 ServiceProvider.AcsURL 都是中间件结构体的导出成员,因此你可以修改/设置它们来实现你想要的效果。
// 生成你的中间件
samlSP, _ := samlsp.New(samlsp.Options{
// 构建中间件所需的任何选项
})
// ServiceProvider.MetadataURL 和 ServiceProvider.AcsURL 都是
// net/url 包中的 url.URL 类型。
// 我们需要使用该类型来表示 /metadata 和 /acs
metadataURL, _ := url.Parse("/metadata")
acsURL, _ := url.Parse("/acs")
samlSP.ServiceProvider.MetadataURL = metadataURL
samlSP.ServiceProvider.AcsURL = acsURL
// 使用中间件
http.Handle("/saml/", samlSP)
编辑:是的。根据文档,你可以简单地更改一些成员来修改行为:samlsp package - github.com/crewjam/saml/samlsp - Go Packages
你可以通过替换和/或更改返回的 Middleware 中的 Session、RequestTracker 和 ServiceProvider 来更详细地自定义中间件的行为。
你可以通过嵌入原始中间件并重写ServeHTTP方法来实现自定义路由。以下是具体实现示例:
package main
import (
"net/http"
"github.com/crewjam/saml/samlsp"
)
type CustomMiddleware struct {
*samlsp.Middleware
}
func (m *CustomMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/metadata" {
m.ServeMetadata(w, r)
return
}
if r.URL.Path == "/acs" {
m.ServeACS(w, r)
return
}
http.NotFoundHandler().ServeHTTP(w, r)
}
// 使用示例
func main() {
// 创建原始中间件
sp, _ := samlsp.New(samlsp.Options{
URL: "https://example.com",
Key: "private-key",
Certificate: "certificate",
IDPMetadata: "idp-metadata",
})
// 包装为自定义中间件
customMiddleware := &CustomMiddleware{Middleware: sp}
// 使用自定义中间件
http.Handle("/", customMiddleware)
http.ListenAndServe(":8080", nil)
}
如果你需要直接调用ServeACS和ServeMetadata,可以通过中间件实例访问:
// 直接调用示例
func handleCustomACS(w http.ResponseWriter, r *http.Request, m *samlsp.Middleware) {
// 直接调用ServeACS
m.ServeACS(w, r)
}
func handleCustomMetadata(w http.ResponseWriter, r *http.Request, m *samlsp.Middleware) {
// 直接调用ServeMetadata
m.ServeMetadata(w, r)
}
这样你就可以完全控制路由逻辑,同时复用原始中间件的认证功能。

