努力理解这些应该如何拼凑在一起。我有一个API,我目前在我的前端使用。我想阻止用户调用某些端点,除非我已经向他们颁发了API密钥。
用户将在authorization
标头中发送密钥。然后,我将键存储在具有不同可能选项的数据库中。
我试图了解最好的方法是排除主站点不受影响或需要提供API密钥。很有可能我做错了。
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)
})
}
作为一个附带问题,当跟踪请求的数量以防止用户达到速率限制时,我应该将他们发出的请求的数量直接存储在数据库中还是仅仅存储在内存中?
可以这样做:
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)
})
}