diff --git a/docs/description.md b/docs/description.md index 0520ad6..584f5b0 100644 --- a/docs/description.md +++ b/docs/description.md @@ -24,3 +24,6 @@ 默认情况下linux对连接数量有限制,对于性能好的机器完全可以调整内核参数以处理更多的连接。 `tcp_max_syn_backlog` `somaxconn` 酌情调整参数,增强网络性能 + +## web管理保护 +当一个ip连续登陆失败次数超过10次,将在一分钟内禁止该ip再次尝试。 diff --git a/web/controllers/login.go b/web/controllers/login.go index 10da8d7..39c5c55 100755 --- a/web/controllers/login.go +++ b/web/controllers/login.go @@ -1,6 +1,9 @@ package controllers import ( + "math/rand" + "net" + "sync" "time" "github.com/astaxie/beego" @@ -13,12 +16,32 @@ type LoginController struct { beego.Controller } +var ipRecord sync.Map + +type record struct { + hasLoginFailTimes int + lastLoginTime time.Time +} + func (self *LoginController) Index() { self.Data["web_base_url"] = beego.AppConfig.String("web_base_url") self.Data["register_allow"], _ = beego.AppConfig.Bool("allow_user_register") self.TplName = "login/index.html" } func (self *LoginController) Verify() { + clearIprecord() + ip, _, _ := net.SplitHostPort(self.Ctx.Request.RemoteAddr) + if v, ok := ipRecord.Load(ip); ok { + vv := v.(*record) + if (time.Now().Unix() - vv.lastLoginTime.Unix()) >= 60 { + vv.hasLoginFailTimes = 0 + } + if vv.hasLoginFailTimes >= 10 { + self.Data["json"] = map[string]interface{}{"status": 0, "msg": "username or password incorrect"} + self.ServeJSON() + return + } + } var auth bool if self.GetString("password") == beego.AppConfig.String("web_password") && self.GetString("username") == beego.AppConfig.String("web_username") { self.SetSession("isAdmin", true) @@ -56,7 +79,14 @@ func (self *LoginController) Verify() { if auth { self.SetSession("auth", true) self.Data["json"] = map[string]interface{}{"status": 1, "msg": "login success"} + ipRecord.Delete(ip) } else { + if v, load := ipRecord.LoadOrStore(ip, &record{hasLoginFailTimes: 1, lastLoginTime: time.Now()}); load { + vv := v.(*record) + vv.lastLoginTime = time.Now() + vv.hasLoginFailTimes += 1 + ipRecord.Store(ip, vv) + } self.Data["json"] = map[string]interface{}{"status": 0, "msg": "username or password incorrect"} } self.ServeJSON() @@ -97,3 +127,17 @@ func (self *LoginController) Out() { self.SetSession("auth", false) self.Redirect(beego.AppConfig.String("web_base_url")+"/login/index", 302) } + +func clearIprecord() { + rand.Seed(time.Now().UnixNano()) + x := rand.Intn(100) + if x == 1 { + ipRecord.Range(func(key, value interface{}) bool { + v := value.(*record) + if time.Now().Unix()-v.lastLoginTime.Unix() >= 60 { + ipRecord.Delete(key) + } + return true + }) + } +}