You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
64 lines
1.5 KiB
64 lines
1.5 KiB
package blademaster
|
|
|
|
import (
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/bilibili/kratos/pkg/log"
|
|
)
|
|
|
|
func matchHostSuffix(suffix string) func(*url.URL) bool {
|
|
return func(uri *url.URL) bool {
|
|
return strings.HasSuffix(strings.ToLower(uri.Host), suffix)
|
|
}
|
|
}
|
|
|
|
func matchPattern(pattern *regexp.Regexp) func(*url.URL) bool {
|
|
return func(uri *url.URL) bool {
|
|
return pattern.MatchString(strings.ToLower(uri.String()))
|
|
}
|
|
}
|
|
|
|
// CSRF returns the csrf middleware to prevent invalid cross site request.
|
|
// Only referer is checked currently.
|
|
func CSRF(allowHosts []string, allowPattern []string) HandlerFunc {
|
|
validations := []func(*url.URL) bool{}
|
|
|
|
addHostSuffix := func(suffix string) {
|
|
validations = append(validations, matchHostSuffix(suffix))
|
|
}
|
|
addPattern := func(pattern string) {
|
|
validations = append(validations, matchPattern(regexp.MustCompile(pattern)))
|
|
}
|
|
|
|
for _, r := range allowHosts {
|
|
addHostSuffix(r)
|
|
}
|
|
for _, p := range allowPattern {
|
|
addPattern(p)
|
|
}
|
|
|
|
return func(c *Context) {
|
|
referer := c.Request.Header.Get("Referer")
|
|
if referer == "" {
|
|
log.V(5).Info("The request's Referer or Origin header is empty.")
|
|
c.AbortWithStatus(403)
|
|
return
|
|
}
|
|
illegal := true
|
|
if uri, err := url.Parse(referer); err == nil && uri.Host != "" {
|
|
for _, validate := range validations {
|
|
if validate(uri) {
|
|
illegal = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if illegal {
|
|
log.V(5).Info("The request's Referer header `%s` does not match any of allowed referers.", referer)
|
|
c.AbortWithStatus(403)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|