Pārlūkot izejas kodu

protecting web management

刘河 5 gadi atpakaļ
vecāks
revīzija
ba081c02c2
2 mainītis faili ar 47 papildinājumiem un 0 dzēšanām
  1. 3 0
      docs/description.md
  2. 44 0
      web/controllers/login.go

+ 3 - 0
docs/description.md

@@ -24,3 +24,6 @@
 默认情况下linux对连接数量有限制,对于性能好的机器完全可以调整内核参数以处理更多的连接。
 `tcp_max_syn_backlog` `somaxconn`
 酌情调整参数,增强网络性能
+
+## web管理保护
+当一个ip连续登陆失败次数超过10次,将在一分钟内禁止该ip再次尝试。

+ 44 - 0
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
+		})
+	}
+}