refactor(10.2-01): nest framework packages under modules
- Move remaining beach packages and embedded admin assets\n- Rewrite framework, example, build, and gate paths
This commit is contained in:
45
modules/cabana/csrf.go
Normal file
45
modules/cabana/csrf.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package cabana
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// requestedWithHeader is the custom header the admin SPA sends on every
|
||||
// request. A cross-site form or navigation cannot set it, and a
|
||||
// cross-origin fetch that sets it needs a CORS preflight the admin API
|
||||
// never answers (D-19).
|
||||
requestedWithHeader = "X-Requested-With"
|
||||
requestedWithAjax = "XMLHttpRequest"
|
||||
)
|
||||
|
||||
// requireAjax refuses a state-changing admin request that is not
|
||||
// Bearer-authenticated and does not carry X-Requested-With: XMLHttpRequest.
|
||||
// It runs before the wrapped handler, so a refused request is never decoded,
|
||||
// never looks up a controller and never reaches the database. The response
|
||||
// uses the fixed D-10 code forbidden.
|
||||
func requireAjax(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if !csrfSafe(r) {
|
||||
WriteError(w, http.StatusForbidden, "forbidden", msgForbidden)
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
func csrfSafe(r *http.Request) bool {
|
||||
switch r.Method {
|
||||
case http.MethodGet, http.MethodHead, http.MethodOptions:
|
||||
return true
|
||||
}
|
||||
if bearerToken(r) != "" {
|
||||
return true
|
||||
}
|
||||
return isAjax(r)
|
||||
}
|
||||
|
||||
func isAjax(r *http.Request) bool {
|
||||
return strings.TrimSpace(r.Header.Get(requestedWithHeader)) == requestedWithAjax
|
||||
}
|
||||
Reference in New Issue
Block a user