- 增加一定时间内登录失败次数的限制

- 增加离线会话保存时间限制
- 完成需求「使会话详情的路径栏可写」close 69
- 修复bug「Ubuntu系统RDP不能正常显示」close 66
- 修复bug「使用guacd接入ssh时,第一个按键被忽略」 close 70
This commit is contained in:
dushixiang
2021-02-23 18:50:13 +08:00
parent 6e2f9e9d90
commit cc9ed70822
15 changed files with 176 additions and 44 deletions

View File

@ -46,19 +46,35 @@ func LoginEndpoint(c echo.Context) error {
}
user, err := model.FindUserByUsername(loginAccount.Username)
// 存储登录失败次数信息
loginFailCountKey := loginAccount.Username
v, ok := global.Cache.Get(loginFailCountKey)
if !ok {
v = 1
}
count := v.(int)
if count >= 5 {
return Fail(c, -1, "登录失败次数过多,请稍后再试")
}
if err != nil {
return Fail(c, -1, "您输入的账号或密码不正确")
count++
global.Cache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
}
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
return Fail(c, -1, "您输入的账号或密码不正确")
count++
global.Cache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
}
if user.TOTPSecret != "" && user.TOTPSecret != "-" {
return Fail(c, 0, "")
}
token, err := Login(c, loginAccount, user)
token, err := LoginSuccess(c, loginAccount, user)
if err != nil {
return err
}
@ -66,7 +82,7 @@ func LoginEndpoint(c echo.Context) error {
return Success(c, token)
}
func Login(c echo.Context, loginAccount LoginAccount, user model.User) (token string, err error) {
func LoginSuccess(c echo.Context, loginAccount LoginAccount, user model.User) (token string, err error) {
token = strings.Join([]string{utils.UUID(), utils.UUID(), utils.UUID(), utils.UUID()}, "")
authorization := Authorization{
@ -75,11 +91,13 @@ func Login(c echo.Context, loginAccount LoginAccount, user model.User) (token st
User: user,
}
cacheKey := strings.Join([]string{Token, token}, ":")
if authorization.Remember {
// 记住登录有效期两周
global.Cache.Set(token, authorization, RememberEffectiveTime)
global.Cache.Set(cacheKey, authorization, RememberEffectiveTime)
} else {
global.Cache.Set(token, authorization, NotRememberEffectiveTime)
global.Cache.Set(cacheKey, authorization, NotRememberEffectiveTime)
}
// 保存登录日志
@ -107,20 +125,37 @@ func loginWithTotpEndpoint(c echo.Context) error {
return err
}
// 存储登录失败次数信息
loginFailCountKey := loginAccount.Username
v, ok := global.Cache.Get(loginFailCountKey)
if !ok {
v = 1
}
count := v.(int)
if count >= 5 {
return Fail(c, -1, "登录失败次数过多,请稍后再试")
}
user, err := model.FindUserByUsername(loginAccount.Username)
if err != nil {
return Fail(c, -1, "您输入的账号或密码不正确")
count++
global.Cache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
}
if err := utils.Encoder.Match([]byte(user.Password), []byte(loginAccount.Password)); err != nil {
return Fail(c, -1, "您输入的账号或密码不正确")
count++
global.Cache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
return FailWithData(c, -1, "您输入的账号或密码不正确", count)
}
if !totp.Validate(loginAccount.TOTP, user.TOTPSecret) {
return Fail(c, -2, "您的TOTP不匹配")
count++
global.Cache.Set(loginFailCountKey, count, time.Minute*time.Duration(5))
return FailWithData(c, -1, "您输入双因素认证授权码不正确", count)
}
token, err := Login(c, loginAccount, user)
token, err := LoginSuccess(c, loginAccount, user)
if err != nil {
return err
}

View File

@ -41,7 +41,8 @@ func Auth(next echo.HandlerFunc) echo.HandlerFunc {
}
token := GetToken(c)
authorization, found := global.Cache.Get(token)
cacheKey := strings.Join([]string{Token, token}, ":")
authorization, found := global.Cache.Get(cacheKey)
if !found {
return Fail(c, 401, "您的登录信息已失效,请重新登录后再试。")
}

View File

@ -156,6 +156,14 @@ func Fail(c echo.Context, code int, message string) error {
})
}
func FailWithData(c echo.Context, code int, message string, data interface{}) error {
return c.JSON(200, H{
"code": code,
"message": message,
"data": data,
})
}
func Success(c echo.Context, data interface{}) error {
return c.JSON(200, H{
"code": 1,

View File

@ -66,15 +66,9 @@ func SessionPagingEndpoint(c echo.Context) error {
func SessionDeleteEndpoint(c echo.Context) error {
sessionIds := c.Param("id")
split := strings.Split(sessionIds, ",")
for i := range split {
drivePath, err := model.GetRecordingPath()
if err != nil {
continue
}
if err := os.RemoveAll(path.Join(drivePath, split[i])); err != nil {
return err
}
model.DeleteSessionById(split[i])
err := model.DeleteSessionByIds(split)
if err != nil {
return err
}
return Success(c, nil)
@ -132,7 +126,7 @@ func CloseSessionById(sessionId string, code int, reason string) {
if s.Status == model.Connecting {
// 会话还未建立成功,无需保留数据
model.DeleteSessionById(sessionId)
_ = model.DeleteSessionById(sessionId)
return
}