basic_auth.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package web
  2. import (
  3. "backup-x/entity"
  4. "backup-x/util"
  5. "bytes"
  6. "encoding/base64"
  7. "log"
  8. "net/http"
  9. "strings"
  10. "time"
  11. )
  12. // ViewFunc func
  13. type ViewFunc func(http.ResponseWriter, *http.Request)
  14. type loginDetect struct {
  15. FailTimes int
  16. }
  17. var ld = &loginDetect{}
  18. // BasicAuth basic auth
  19. func BasicAuth(f ViewFunc) ViewFunc {
  20. return func(w http.ResponseWriter, r *http.Request) {
  21. conf, _ := entity.GetConfigCache()
  22. // 帐号或密码为空。跳过
  23. if conf.Username == "" && conf.Password == "" {
  24. // 执行被装饰的函数
  25. f(w, r)
  26. return
  27. }
  28. if ld.FailTimes >= 5 {
  29. log.Printf("%s 登录失败超过5次! 并延时5分钟响应\n", r.RemoteAddr)
  30. time.Sleep(5 * time.Minute)
  31. if ld.FailTimes >= 5 {
  32. ld.FailTimes = 0
  33. }
  34. w.WriteHeader(http.StatusUnauthorized)
  35. return
  36. }
  37. // 认证帐号密码
  38. basicAuthPrefix := "Basic "
  39. // 获取 request header
  40. auth := r.Header.Get("Authorization")
  41. // 如果是 http basic auth
  42. if strings.HasPrefix(auth, basicAuthPrefix) {
  43. // 解码认证信息
  44. payload, err := base64.StdEncoding.DecodeString(
  45. auth[len(basicAuthPrefix):],
  46. )
  47. if err == nil {
  48. pair := bytes.SplitN(payload, []byte(":"), 2)
  49. pwd, _ := util.DecryptByEncryptKey(conf.EncryptKey, conf.Password)
  50. if len(pair) == 2 &&
  51. bytes.Equal(pair[0], []byte(conf.Username)) &&
  52. bytes.Equal(pair[1], []byte(pwd)) {
  53. ld.FailTimes = 0
  54. // 执行被装饰的函数
  55. f(w, r)
  56. return
  57. }
  58. }
  59. ld.FailTimes = ld.FailTimes + 1
  60. log.Printf("%s 登录失败!\n", r.RemoteAddr)
  61. }
  62. // 认证失败,提示 401 Unauthorized
  63. // Restricted 可以改成其他的值
  64. w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
  65. // 401 状态码
  66. w.WriteHeader(http.StatusUnauthorized)
  67. log.Printf("%s 请求登录!\n", r.RemoteAddr)
  68. }
  69. }