大猩猩中间件对特定路由的身份验证不起作用。

huangapple go评论84阅读模式
英文:

Gorilla middleware authentication for specific routes not working

问题

我正在为一个API编写一个HTTP路由器,其中一些路由需要身份验证,而另一些则不需要。

我不想在每个路由上都要求身份验证,所以我将它们分开。

但是有一个问题:

POST /account <-- 这是一个账户注册端点,不需要身份验证

DELETE /account <-- 这需要身份验证才能删除当前账户

我不知道如何正确分离它们,而且我目前尝试的将中间件分别应用于这两个路由的方法失败了:

package httpServer

import (
	"log"
	"net/http"
	"httpServer/handlers"
	"httpServer/middlewares"

	"github.com/gorilla/mux"
	"github.com/justinas/alice"
)

func Init() {
	log.Println("Initializing http routes...")

	defaultmiddlewares := alice.New(middlewares.Logger, middlewares.Recover)
	authmiddlewares := alice.New(middlewares.Authenticator)

	var mainRouter = mux.NewRouter()
	var authRouter = mux.NewRouter()

	// 不需要身份验证调用此路由
	mainRouter.HandleFunc("/health", handlers.HealthGet).Methods("GET")        // 获取API健康状态

    // authRouter 应该是 mainRouter 的扩展(我认为)
    mainRouter.Handle("/", authmiddlewares.Then(authRouter))

    // 不需要身份验证调用此路由
	mainRouter.HandleFunc("/account", handlers.AccountPost).Methods("POST")                    // 创建账户

    // 需要身份验证调用此路由
	authRouter.HandleFunc("/account", handlers.AccountDelete).Methods("DELETE")                // 删除我的账户

    // WebSocket 端点
	authRouter.HandleFunc("/ws", handlers.UpgradeWs)
	authRouter.HandleFunc("/ws/", handlers.UpgradeWs) // 如果我不添加这个,它就无法工作??
    
    // 注册 mainRouter
	http.Handle("/", defaultmiddlewares.Then(mainRouter))
}

GET /health 的调用是正常的:大猩猩中间件对特定路由的身份验证不起作用。
但是对 DELETE /account 的调用失败,返回 404 Not Found大猩猩中间件对特定路由的身份验证不起作用。

(还有,在 Init() 函数的末尾,我注册了一个 WebSocket 端点,由于某种原因,如果我不注册这两个端点,它就无法连接?)

英文:

Im writing a http router for a API and some routes require authentication while some dont.

I dont want to ask for authentication on every route, so I split them up.

But theres a problem:

POST /account <-- This is a account registration endpoint, and does not require authentication

DELETE /account <-- This does require authentication to delete the current account

I have no idea how to seperate these properly, also my current attempt at making the middleware different for the two is failing:

package httpServer

import (
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;httpServer/handlers&quot;
	&quot;httpServer/middlewares&quot;

	&quot;github.com/gorilla/mux&quot;
	&quot;github.com/justinas/alice&quot;
)

func Init() {
	log.Println(&quot;Initializing http routes...&quot;)

	defaultmiddlewares := alice.New(middlewares.Logger, middlewares.Recover)
	authmiddlewares := alice.New(middlewares.Authenticator)

	var mainRouter = mux.NewRouter()
	var authRouter = mux.NewRouter()

	// No auth required to call this
	mainRouter.HandleFunc(&quot;/health&quot;, handlers.HealthGet).Methods(&quot;GET&quot;)        // Get API health

    // authrouter should be a extension of main router (i think)
    mainRouter.Handle(&quot;/&quot;, authmiddlewares.Then(authRouter))

    // Authentication is not required for this
	mainRouter.HandleFunc(&quot;/account&quot;, handlers.AccountPost).Methods(&quot;POST&quot;)                    // Create an account

    // Authentication is required for this
	authRouter.HandleFunc(&quot;/account&quot;, handlers.AccountDelete).Methods(&quot;DELETE&quot;)                // Delete my account

    // WebSocket endpoint:
	authRouter.HandleFunc(&quot;/ws&quot;, handlers.UpgradeWs)
	authRouter.HandleFunc(&quot;/ws/&quot;, handlers.UpgradeWs) // If i dont add this it doesnt work??
    
    // Register mainRouter
	http.Handle(&quot;/&quot;, defaultmiddlewares.Then(mainRouter))
}

Calls to GET /health are just fine:大猩猩中间件对特定路由的身份验证不起作用。
But calls to DELETE /account are failing with a 404 Not Found:大猩猩中间件对特定路由的身份验证不起作用。

(Also near the end of the Init() function i register a websocket endpoint, for some reason if i dont register both those endpoints it fails to connect?)

答案1

得分: 2

你初始化了两个路由器 mainRouterauthRouter,但只启动了 mainRouterDELETE /account 绑定到了 authRouter,但是它没有被启动和监听。这就是为什么会返回 404 错误的原因。

你可以编写自定义的中间件实现,使用 gorilla/mux 路由器的 gorilla/mux 中间件接口。示例代码如下:

func Init() {
	log.Println("Initializing http routes...")
	
	r := mux.NewRouter()
	middleware := Middleware{
		// 如果需要,可以注入任何依赖项
	}
	r.Use(middleware.MiddlewareFunc)

	// 不需要身份验证调用此接口
	r.HandleFunc("/health", handlers.HealthGet).Methods("GET") // 获取 API 健康状态

	// authRouter 应该是 mainRouter 的扩展(我认为)
	r.Handle("/", authmiddlewares.Then(authRouter))

	// 此接口不需要身份验证
	r.HandleFunc("/account", handlers.AccountPost).Methods("POST") // 创建账户

	// 此接口需要身份验证
	r.HandleFunc("/account", handlers.AccountDelete).Methods("DELETE") // 删除我的账户

	http.ListenAndServe(":8080", r)
}

// Middleware 是你自定义的中间件实现
type Middleware struct {}

func (m Middleware) MiddlewareFunc(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 在这里你可以检查请求方法和路径,并进行身份验证
		// 例如:如果方法为 DELETE,路径为 /account,则进行身份验证

		handler.ServeHTTP(w, r)
	})
}
英文:

You initialised two routers mainRouter and authRouter and only start mainRouter. DELETE /account is bound to authRouter . That is not started and listening. That is why 404 coming.

And you can write custom middleware implementations to gorilla/mux Middleware interface and use with gorilla/mux router. Example code is like below

func Init() {
log.Println(&quot;Initializing http routes...&quot;)
r := mux.NewRouter()
middleware := Middleware{
// inject any dependency if you need
}
r.Use(middleware.MiddlewareFunc)
// No auth required to call this
r.HandleFunc(&quot;/health&quot;, handlers.HealthGet).Methods(&quot;GET&quot;)        // Get API health
// authrouter should be a extension of main router (i think)
r.Handle(&quot;/&quot;, authmiddlewares.Then(authRouter))
// Authentication is not required for this
r.HandleFunc(&quot;/account&quot;, handlers.AccountPost).Methods(&quot;POST&quot;)                    // Create an account
// Authentication is required for this
r.HandleFunc(&quot;/account&quot;, handlers.AccountDelete).Methods(&quot;DELETE&quot;)                // Delete my account
http.ListenAndServe(&quot;:8080&quot;, r)
}
// Middleware your custom middleware implementation
type Middleware struct {}
func (m Middleware) MiddlewareFunc(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// you can check request method and paths and you can do authentications here
//eg := method = DELETE and path = /account, do authentication
handler.ServeHTTP(w, r)
})
}

huangapple
  • 本文由 发表于 2021年8月20日 09:41:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/68856077.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定