csrf.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package blademaster
  2. import (
  3. "net/url"
  4. "regexp"
  5. "strings"
  6. "go-common/library/log"
  7. )
  8. var (
  9. _allowHosts = []string{
  10. ".bilibili.com",
  11. ".bilibili.co",
  12. ".biligame.com",
  13. ".im9.com",
  14. ".acg.tv",
  15. ".hdslb.com",
  16. }
  17. _allowPatterns = []string{
  18. // match by wechat appid
  19. `^http(?:s)?://([\w\d]+\.)?servicewechat.com/(wx7564fd5313d24844|wx618ca8c24bf06c33)`,
  20. }
  21. validations = []func(*url.URL) bool{}
  22. )
  23. func matchHostSuffix(suffix string) func(*url.URL) bool {
  24. return func(uri *url.URL) bool {
  25. return strings.HasSuffix(strings.ToLower(uri.Host), suffix)
  26. }
  27. }
  28. func matchPattern(pattern *regexp.Regexp) func(*url.URL) bool {
  29. return func(uri *url.URL) bool {
  30. return pattern.MatchString(strings.ToLower(uri.String()))
  31. }
  32. }
  33. // addHostSuffix add host suffix into validations
  34. func addHostSuffix(suffix string) {
  35. validations = append(validations, matchHostSuffix(suffix))
  36. }
  37. // addPattern add referer pattern into validations
  38. func addPattern(pattern string) {
  39. validations = append(validations, matchPattern(regexp.MustCompile(pattern)))
  40. }
  41. func init() {
  42. for _, r := range _allowHosts {
  43. addHostSuffix(r)
  44. }
  45. for _, p := range _allowPatterns {
  46. addPattern(p)
  47. }
  48. }
  49. // CSRF returns the csrf middleware to prevent invalid cross site request.
  50. // Only referer is checked currently.
  51. func CSRF() HandlerFunc {
  52. return func(c *Context) {
  53. referer := c.Request.Header.Get("Referer")
  54. params := c.Request.Form
  55. cross := (params.Get("callback") != "" && params.Get("jsonp") == "jsonp") || (params.Get("cross_domain") != "")
  56. if referer == "" {
  57. if !cross {
  58. return
  59. }
  60. log.V(5).Info("The request's Referer header is empty.")
  61. c.AbortWithStatus(403)
  62. return
  63. }
  64. illegal := true
  65. if uri, err := url.Parse(referer); err == nil && uri.Host != "" {
  66. for _, validate := range validations {
  67. if validate(uri) {
  68. illegal = false
  69. break
  70. }
  71. }
  72. }
  73. if illegal {
  74. log.V(5).Info("The request's Referer header `%s` does not match any of allowed referers.", referer)
  75. c.AbortWithStatus(403)
  76. return
  77. }
  78. }
  79. }