缩略图懒生成 + 评论登录限流:时间线不再拉原图
- 新增 /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:
@@ -14,6 +14,7 @@ import (
|
||||
"oneblog/internal/auth"
|
||||
"oneblog/internal/httpx"
|
||||
"oneblog/internal/model"
|
||||
"oneblog/internal/ratelimit"
|
||||
)
|
||||
|
||||
// authProviders 列出已配置的登录方式。
|
||||
@@ -79,18 +80,26 @@ func (a *API) googleCallback(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
|
||||
}
|
||||
accessToken, err := a.GG.Exchange(r.Context(), r.FormValue("code"), a.Cfg.SiteURL+"/api/auth/callback/google")
|
||||
if err != nil {
|
||||
a.authFails.Add(ip)
|
||||
httpx.ServerError(w, err)
|
||||
return
|
||||
}
|
||||
u, err := a.GG.FetchUser(r.Context(), accessToken)
|
||||
if err != nil {
|
||||
a.authFails.Add(ip)
|
||||
httpx.ServerError(w, err)
|
||||
return
|
||||
}
|
||||
@@ -121,6 +130,12 @@ func (a *API) telegramAuth(w http.ResponseWriter, r *http.Request) {
|
||||
httpx.NotFound(w)
|
||||
return
|
||||
}
|
||||
// widget 回传是纯表单 POST,签名可被伪造重放——失败计数最必要的一路
|
||||
ip := ratelimit.SourceKey(r)
|
||||
if a.authFails.Blocked(ip) {
|
||||
httpx.Error(w, http.StatusTooManyRequests, "登录失败次数过多,请稍后再试")
|
||||
return
|
||||
}
|
||||
// 原样读 body:验签必须用收到的全部字段(官方规则),
|
||||
// 身份字段再单独解一次
|
||||
body, err := io.ReadAll(r.Body)
|
||||
@@ -130,10 +145,12 @@ func (a *API) telegramAuth(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
var fields map[string]any
|
||||
if err := json.Unmarshal(body, &fields); err != nil || len(fields) == 0 {
|
||||
a.authFails.Add(ip)
|
||||
httpx.BadRequest(w, "invalid body")
|
||||
return
|
||||
}
|
||||
if err := a.TG.VerifyMap(fields); err != nil {
|
||||
a.authFails.Add(ip)
|
||||
httpx.Error(w, http.StatusForbidden, "Telegram 登录校验失败,请重试")
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user