缩略图懒生成 + 评论登录限流:时间线不再拉原图
- 新增 /uploads/thumb/{key}?w=:首访从存储端读一次原图,标准库盒均值缩放后
落盘 data/.thumbnail_cache(按内容哈希命名,天然失效);失败写 .failed 冷却
一小时,非图片/超大一律 302 回原图,前端无感。原图路由改用 ServeContent,
补上视频拖动进度条所需的 Range 支持
- 前端 thumbURL/thumbifyHtml 接入两套 UI 的时间线配图、长文封面与短文正文,
并补 loading=lazy;详情页与灯箱仍用原图。/api/site 改为
{settings, uploads_public_base},让前端识别哪些直链属于自家存储
- 后台登录的滑动窗口限速器抽成 internal/ratelimit 共享包(调用面不变),
新增:读者登录失败按 IP 20 次/10 分钟、评论写入按读者 5 条/分钟
(站主豁免,且只计成功写入)
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"oneblog/internal/auth"
|
||||
"oneblog/internal/httpx"
|
||||
"oneblog/internal/model"
|
||||
"oneblog/internal/ratelimit"
|
||||
"oneblog/internal/render"
|
||||
"oneblog/internal/store"
|
||||
)
|
||||
@@ -121,18 +122,26 @@ func (a *API) githubCallback(w http.ResponseWriter, r *http.Request) {
|
||||
httpx.NotFound(w)
|
||||
return
|
||||
}
|
||||
ip := ratelimit.SourceKey(r)
|
||||
if a.authFails.Blocked(ip) {
|
||||
httpx.Error(w, http.StatusTooManyRequests, "登录失败次数过多,请稍后再试")
|
||||
return
|
||||
}
|
||||
ck, err := r.Cookie(oauthStateCook)
|
||||
if err != nil || ck.Value == "" || ck.Value != r.FormValue("state") {
|
||||
a.authFails.Add(ip)
|
||||
httpx.BadRequest(w, "state 不匹配,请重新登录")
|
||||
return
|
||||
}
|
||||
gh, err := a.GH.Exchange(r.Context(), r.FormValue("code"), a.Cfg.SiteURL+"/api/auth/callback/github")
|
||||
if err != nil {
|
||||
a.authFails.Add(ip)
|
||||
httpx.ServerError(w, err)
|
||||
return
|
||||
}
|
||||
u, err := a.GH.FetchUser(r.Context(), gh)
|
||||
if err != nil {
|
||||
a.authFails.Add(ip)
|
||||
httpx.ServerError(w, err)
|
||||
return
|
||||
}
|
||||
@@ -206,6 +215,15 @@ func (a *API) createComment(w http.ResponseWriter, r *http.Request) {
|
||||
httpx.Error(w, http.StatusForbidden, "你已被禁言,暂时无法评论")
|
||||
return
|
||||
}
|
||||
// 写入限速:每读者每分钟最多 maxComments 条(站主豁免,批量回复不该被卡)
|
||||
var rateKey string
|
||||
if !isOwner {
|
||||
rateKey = strconv.FormatInt(reader.ID, 10)
|
||||
if a.commentNew.Blocked(rateKey) {
|
||||
httpx.Error(w, http.StatusTooManyRequests, "发得太快了,休息一分钟再试")
|
||||
return
|
||||
}
|
||||
}
|
||||
st, err := a.Store.GetSettings()
|
||||
if err != nil {
|
||||
httpx.ServerError(w, err)
|
||||
@@ -267,6 +285,9 @@ func (a *API) createComment(w http.ResponseWriter, r *http.Request) {
|
||||
httpx.ServerError(w, err)
|
||||
return
|
||||
}
|
||||
if rateKey != "" {
|
||||
a.commentNew.Add(rateKey) // 只计成功写入:空正文这类手滑不扣配额
|
||||
}
|
||||
httpx.Created(w, c)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user