Go语言中如何合并Gorilla Mux的认证与非认证路由?
合并Gorilla Mux的认证与非认证路由
我有如下Go代码,包含两个Gorilla Mux路由:一个非认证路由(r),另一个是通过Alice中间件包装的认证路由(chain)。希望将两个路由合并后提供服务。
package main import ( "ekart.com/authentication_service/models" "fmt" "log" "net/http" "github.com/gorilla/mux" "github.com/justinas/alice" ) func main() { var JSON_SECRET []byte = []byte("TZWfMhBEuyzsc2e52wQQaDxfBriktka9GR4BhBtH9PhXi6XHwyaaaUyxBc-yd1RtYKsiFAGXZcBJuQ6ML5UGBEEx72Qhw6Q-192msUDwMHxT3Scz5wWnk--Bp8wotvu7FS2-v88cvC52e1lfG8mr60dGu7kg-jzcRa5cDTfR4KMQIAD6lO1H3J6f48u46gLjQtzOLPH9yjx0mqVtGWmaizGMQE7NdrhHH5ZlMuuj-A6lZRjf2VZKxUiFFWmfnVMhPVh-wpOybMaFzhUjm-RWXQ-E6cCeI-sBzcu5ZJ8aZVnYPc1Inc5RJ9R5rKQblctxHt5QCYlxiFHb63aO36ZS0Q") var DSN string = "root:toor@tcp(localhost:3306)/ekart_auth?charset=utf8&parseTime=True&loc=Local" app := Config{secret: JSON_SECRET} app.NewDatabaseConnection(DSN) app.DB.AutoMigrate(&models.User{}) r := mux.NewRouter() r.HandleFunc("/login", app.Login).Methods("POST") r.HandleFunc("/register", app.Register).Methods("POST") authmux := mux.NewRouter() authmux.HandleFunc("/onlyauth", app.OnlyIfAuthenticated).Methods("GET") chain := alice.New(app.Authenticate).Then(authmux) log.Print(fmt.Sprintf("Starting Server on port %d", 8080)) log.Fatal(http.ListenAndServe(fmt.Sprintf(":%v", 8080), r)) }
我尝试过合并路由的方法但未成功,也试过Gorilla Mux官方文档中的路径前缀方式:
s := r.PathPrefix("/auth").Subrouter() s.HandleFunc("/", chain.ServeHTTP)
同样无效。最好无需创建子路径,若必须创建也可接受。
解决方案
方案1:无需子路径,给单个认证接口添加中间件
直接在主路由上为需要认证的接口单独应用Alice中间件,无需额外创建路由:
func main() { // ... 省略数据库初始化等代码 ... r := mux.NewRouter() // 非认证接口 r.HandleFunc("/login", app.Login).Methods("POST") r.HandleFunc("/register", app.Register).Methods("POST") // 为需要认证的接口包装中间件 authChain := alice.New(app.Authenticate) r.Handle("/onlyauth", authChain.ThenFunc(app.OnlyIfAuthenticated)).Methods("GET") log.Print("Starting Server on port 8080") log.Fatal(http.ListenAndServe(":8080", r)) }
方案2:无需子路径,给一组认证接口统一加中间件
如果有多个需要认证的接口,可以创建主路由的子路由,然后给子路由绑定认证中间件:
func main() { // ... 省略数据库初始化等代码 ... r := mux.NewRouter() // 非认证接口 r.HandleFunc("/login", app.Login).Methods("POST") r.HandleFunc("/register", app.Register).Methods("POST") // 创建子路由并应用认证中间件 authSubrouter := r.PathPrefix("").Subrouter() authSubrouter.Use(func(next http.Handler) http.Handler { return app.Authenticate(next) }) // 所有子路由下的接口都会经过认证 authSubrouter.HandleFunc("/onlyauth", app.OnlyIfAuthenticated).Methods("GET") // 可添加更多认证接口 // authSubrouter.HandleFunc("/profile", app.GetProfile).Methods("GET") log.Print("Starting Server on port 8080") log.Fatal(http.ListenAndServe(":8080", r)) }
方案3:接受子路径,正确挂载认证路由
如果可以接受子路径,之前的错误在于使用了HandleFunc,正确的做法是用Handler方法将认证路由挂载到主路由:
func main() { // ... 省略数据库初始化等代码 ... r := mux.NewRouter() // 非认证接口 r.HandleFunc("/login", app.Login).Methods("POST") r.HandleFunc("/register", app.Register).Methods("POST") // 认证路由 authmux := mux.NewRouter() authmux.HandleFunc("/onlyauth", app.OnlyIfAuthenticated).Methods("GET") chain := alice.New(app.Authenticate).Then(authmux) // 正确挂载认证路由到子路径 r.PathPrefix("/auth").Handler(chain) log.Print("Starting Server on port 8080") log.Fatal(http.ListenAndServe(":8080", r)) }
此时访问认证接口的路径为/auth/onlyauth。
内容的提问来源于stack exchange,提问作者Sushant
相关产品推荐
相关产品推荐

