英文:
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)
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论