理解如何正确地为第三方实现 API 密钥

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

Understanding how to properly implement API Keys for only third parties

问题

我正在努力理解这个问题应该如何组合在一起。我有一个API,目前在我的前端上使用。我想要防止用户调用某些端点,除非我已经为他们发放了API密钥。

用户将在authorization头部发送密钥。然后,我将密钥存储在数据库中,有不同的可能选项。

我试图理解最佳方法是什么,以排除主站点受到影响或需要提供API密钥。很可能我在处理这个问题的方式上是错误的。

另外一个问题是,当跟踪请求次数以防止用户达到速率限制时,我应该直接将他们的请求次数存储在数据库中还是只存储在内存中?

英文:

Struggling to understand exactly how this should be pieced together. I have an API that I'm currently using on my frontend. I'd like prevent users from calling certain endpoints unless I've issued them an API key.

Users will be sending the key in the authorization header. I then have the keys stored in a database with different possible options.

I'm trying to understand what the best method would be to exclude the main site from being affected or needing to provide an API key. It's very possible I'm going about this the wrong way.

func APIRequestMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		hostIP, _, err := net.SplitHostPort(r.RemoteAddr)
		if err != nil {
			logerr.FromError(err)
			hostIP = r.RemoteAddr
		}
		if string_util.StringInArray(&hostIP, []string{
			"my.clients.ip?",
		}) {
			next.ServeHTTP(w, r)
		}
		auth := r.Header.Get("authorization")
		type tokenDetails struct {
			Token      string
			Expires_at time.Time
			Rate_limit int
			Enabled    bool
			Created    time.Time
		}
		var details tokenDetails
		err = sqlx.Get(database.AccountDB, details, `Select * from keys where token = $1`, auth)
		if err != nil {
			request_util.InvalidTokenResponse(w, r)
			return
		}

		if details.Expires_at.Before(time.Now()) {
			request_util.InvalidTokenResponse(w, r)
			return
		}
		if !details.Enabled {
			request_util.InvalidTokenResponse(w, r)
			return
		}

		// Track # of requests
		// if currentRequest > details.Rate_limit {
		// 	request_util.InvalidTokenResponse(w, r)
		// 	return
		// }
		next.ServeHTTP(w, r)
	})
}

As a side question, when tracking the number of requests to prevent a user from hitting a rate limit, should I be storing the # of requests they make directly in the database or just in memory?

答案1

得分: 1

这样的代码可以工作:

var allowedPaths = map[string]bool{
	"GET/abc": true,
}

func APIRequestMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if _, ok := allowedPaths[r.Method+r.URL.Path]; ok {
			 next.ServeHTTP(w, r)
			 return
		}
		
        auth := r.Header.Get("authorization")
        type tokenDetails struct {
            Token      string
            Expires_at time.Time
            Rate_limit int
            Enabled    bool
            Created    time.Time
        }
        var details tokenDetails
        err = sqlx.Get(database.AccountDB, details, `Select * from keys where token = $1`, auth)
        if err != nil {
            request_util.InvalidTokenResponse(w, r)
            return
        }

        if details.Expires_at.Before(time.Now()) {
            request_util.InvalidTokenResponse(w, r)
            return
        }
        if !details.Enabled {
            request_util.InvalidTokenResponse(w, r)
            return
        }

        // Track # of requests
        // if currentRequest > details.Rate_limit {
        //  request_util.InvalidTokenResponse(w, r)
        //  return
        // }
        next.ServeHTTP(w, r)
    })
}

希望对你有帮助!

英文:

Something like this would work:

var allowedPaths = map[string]bool{
	"GET/abc": true,
}

func APIRequestMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if _, ok := allowedPaths[r.Method+r.URL.Path]; ok {
			 next.ServeHTTP(w, r)
			 return
		}
		
        auth := r.Header.Get("authorization")
        type tokenDetails struct {
            Token      string
            Expires_at time.Time
            Rate_limit int
            Enabled    bool
            Created    time.Time
        }
        var details tokenDetails
        err = sqlx.Get(database.AccountDB, details, `Select * from keys where token = $1`, auth)
        if err != nil {
            request_util.InvalidTokenResponse(w, r)
            return
        }

        if details.Expires_at.Before(time.Now()) {
            request_util.InvalidTokenResponse(w, r)
            return
        }
        if !details.Enabled {
            request_util.InvalidTokenResponse(w, r)
            return
        }

        // Track # of requests
        // if currentRequest > details.Rate_limit {
        //  request_util.InvalidTokenResponse(w, r)
        //  return
        // }
        next.ServeHTTP(w, r)
    })
}

huangapple
  • 本文由 发表于 2022年6月30日 05:14:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/72807953.html
匿名

发表评论

匿名网友

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

确定