0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-24 07:29:08 -05:00

🎉 Add ratelimit for login handler.

Will prevent DOS on executing resource demanding handler such
as login.
This commit is contained in:
Andrey Antukh 2020-01-13 15:12:38 +01:00
parent a8f84aa93d
commit 2420f7de9e
3 changed files with 68 additions and 2 deletions

View file

@ -27,6 +27,9 @@
io.vertx/vertx-pg-client {:mvn/version "3.8.4"}
;; end verx deps
io.github.resilience4j/resilience4j-core {:mvn/version "1.2.0"}
io.github.resilience4j/resilience4j-ratelimiter {:mvn/version "1.2.0"}
lambdaisland/uri {:mvn/version "1.1.0"}
danlentz/clj-uuid {:mvn/version "0.1.9"}

View file

@ -16,6 +16,7 @@
[uxbox.http.session :as session]
[uxbox.http.handlers :as handlers]
[uxbox.http.debug :as debug]
[uxbox.http.ratelimit :as rl]
[uxbox.http.ws :as ws]
[vertx.core :as vc]
[vertx.http :as vh]
@ -44,6 +45,18 @@
interceptors/format-response-body
(vxi/errors errors/handle)]
login-handler (rl/ratelimit handlers/login-handler
{:limit 10
:period 1000
:timeout 200
:name "login-handler"})
echo-handler (rl/ratelimit handlers/echo-handler
{:limit 100
:period 1000
:timeout 1000
:name "echo-handler"})
routes [["/sub/:file-id" {:interceptors [(vxi/cookies)
(vxi/cors cors-opts)
interceptors/format-response-body
@ -51,8 +64,8 @@
:get ws/handler}]
["/api" {:interceptors interceptors}
["/echo" {:all handlers/echo-handler}]
["/login" {:post handlers/login-handler}]
["/echo" {:all echo-handler}]
["/login" {:post login-handler}]
["/logout" {:post handlers/logout-handler}]
["/register" {:post handlers/register-handler}]
["/debug"

View file

@ -0,0 +1,50 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.http.ratelimit
"Rate limit"
(:require
[clojure.spec.alpha :as s]
[uxbox.common.exceptions :as ex]
[uxbox.core :refer [system]]
[vertx.core :as vc]
[promesa.core :as p]
[promesa.exec :as pe])
(:import
io.github.resilience4j.ratelimiter.RateLimiter
io.github.resilience4j.ratelimiter.RateLimiterConfig
io.github.resilience4j.ratelimiter.RateLimiterRegistry
java.util.concurrent.CompletableFuture
java.util.function.Supplier
java.time.Duration))
;; --- Rate Limiter
(def ^:private registry (RateLimiterRegistry/ofDefaults))
(defn- opts->rate-limiter-config
[{:keys [limit period timeout] :as opts}]
(let [custom (RateLimiterConfig/custom)]
(.limitRefreshPeriod custom (Duration/ofMillis period))
(.limitForPeriod custom limit)
(.timeoutDuration custom (Duration/ofMillis timeout))
(.build custom)))
(defn ratelimit
[f {:keys [name] :as opts}]
(let [config (opts->rate-limiter-config opts)
rl (.rateLimiter registry name config)]
(fn [& args]
(let [ctx (vc/get-or-create-context system)]
(-> (pe/run! #(when-not (.acquirePermission rl 1)
(ex/raise :type :ratelimit
:code :timeout
:context {:name name})))
(vc/handle-on-context)
(p/bind (fn [_] (p/do! (apply f args)))))))))