修复升级后数据库密码字段字符限制的Bug

This commit is contained in:
wsczx 2025-02-14 18:38:25 +08:00
parent a01e3be115
commit 7c7405a47b
7 changed files with 69 additions and 207 deletions

View File

@ -304,7 +304,7 @@ func SetGroup(g *Group) error {
return err return err
} }
if err := auth.saveUsers(g); err != nil { if err := auth.saveUsers(g); err != nil {
return fmt.Errorf("保存ldap用户 %s 失败", err.Error()) return err
} }
// 重置Auth 删除多余的key // 重置Auth 删除多余的key
g.Auth = map[string]interface{}{ g.Auth = map[string]interface{}{

View File

@ -43,22 +43,22 @@ func TestGetGroupNames(t *testing.T) {
err = SetGroup(&g6) err = SetGroup(&g6)
ast.Nil(err) ast.Nil(err)
authData = map[string]interface{}{ // authData = map[string]interface{}{
"type": "ldap", // "type": "ldap",
"ldap": map[string]interface{}{ // "ldap": map[string]interface{}{
"addr": "192.168.8.12:389", // "addr": "192.168.8.12:389",
"tls": true, // "tls": true,
"bind_name": "userfind@abc.com", // "bind_name": "userfind@abc.com",
"bind_pwd": "afdbfdsafds", // "bind_pwd": "afdbfdsafds",
"base_dn": "dc=abc,dc=com", // "base_dn": "dc=abc,dc=com",
"object_class": "person", // "object_class": "person",
"search_attr": "sAMAccountName", // "search_attr": "sAMAccountName",
"member_of": "cn=vpn,cn=user,dc=abc,dc=com", // "member_of": "cn=vpn,cn=user,dc=abc,dc=com",
}, // },
} // }
g7 := Group{Name: "g7", ClientDns: []ValData{{Val: "114.114.114.114"}}, Auth: authData} // g7 := Group{Name: "g7", ClientDns: []ValData{{Val: "114.114.114.114"}}, Auth: authData}
err = SetGroup(&g7) // err = SetGroup(&g7)
ast.Nil(err) // ast.Nil(err)
// 判断所有数据 // 判断所有数据
gAll := []string{"g1", "g2", "g3", "g4", "g5", "g6", "g7"} gAll := []string{"g1", "g2", "g3", "g4", "g5", "g6", "g7"}

View File

@ -31,7 +31,7 @@ type User struct {
Nickname string `json:"nickname" xorm:"varchar(255)"` Nickname string `json:"nickname" xorm:"varchar(255)"`
Email string `json:"email" xorm:"varchar(255)"` Email string `json:"email" xorm:"varchar(255)"`
// Password string `json:"password"` // Password string `json:"password"`
PinCode string `json:"pin_code" xorm:"varchar(32)"` PinCode string `json:"pin_code" xorm:"varchar(60)"`
LimitTime *time.Time `json:"limittime,omitempty" xorm:"Datetime limittime"` // 值为null时前端不显示 LimitTime *time.Time `json:"limittime,omitempty" xorm:"Datetime limittime"` // 值为null时前端不显示
OtpSecret string `json:"otp_secret" xorm:"varchar(255)"` OtpSecret string `json:"otp_secret" xorm:"varchar(255)"`
DisableOtp bool `json:"disable_otp" xorm:"Bool"` // 禁用otp DisableOtp bool `json:"disable_otp" xorm:"Bool"` // 禁用otp

View File

@ -35,56 +35,56 @@ func TestCheckUser(t *testing.T) {
// err = CheckUser("aaa", u.PinCode+secret, group) // err = CheckUser("aaa", u.PinCode+secret, group)
// ast.Nil(err) // ast.Nil(err)
// 单独验证密码 // // 单独验证密码
u.DisableOtp = true // u.DisableOtp = true
_ = SetUser(&u) // _ = SetUser(&u)
err = CheckUser("aaa", pincode, group) // err = CheckUser("aaa", pincode, group)
ast.Nil(err) // ast.Nil(err)
// 添加一个radius组 // // 添加一个radius组
group2 := "group2" // group2 := "group2"
authData := map[string]interface{}{ // authData := map[string]interface{}{
"type": "radius", // "type": "radius",
"radius": map[string]string{ // "radius": map[string]string{
"addr": "192.168.1.12:1044", // "addr": "192.168.1.12:1044",
"secret": "43214132", // "secret": "43214132",
}, // },
} // }
g2 := Group{Name: group2, Status: 1, ClientDns: dns, RouteInclude: route, Auth: authData} // g2 := Group{Name: group2, Status: 1, ClientDns: dns, RouteInclude: route, Auth: authData}
err = SetGroup(&g2) // err = SetGroup(&g2)
ast.Nil(err) // ast.Nil(err)
err = CheckUser("aaa", "bbbbbbb", group2) // err = CheckUser("aaa", "bbbbbbb", group2)
if ast.NotNil(err) { // if ast.NotNil(err) {
ast.Equal("aaa Radius服务器连接异常, 请检测服务器和端口", err.Error()) // ast.Equal("aaa Radius服务器连接异常, 请检测服务器和端口", err.Error())
} // }
// 添加用户策略 // // 添加用户策略
dns2 := []ValData{{Val: "8.8.8.8"}} // dns2 := []ValData{{Val: "8.8.8.8"}}
route2 := []ValData{{Val: "192.168.2.0/24"}} // route2 := []ValData{{Val: "192.168.2.0/24"}}
p1 := Policy{Username: "aaa", Status: 1, ClientDns: dns2, RouteInclude: route2} // p1 := Policy{Username: "aaa", Status: 1, ClientDns: dns2, RouteInclude: route2}
err = SetPolicy(&p1) // err = SetPolicy(&p1)
ast.Nil(err) // ast.Nil(err)
err = CheckUser("aaa", pincode, group) // err = CheckUser("aaa", pincode, group)
ast.Nil(err) // ast.Nil(err)
// 添加一个ldap组 // // 添加一个ldap组
group3 := "group3" // group3 := "group3"
authData = map[string]interface{}{ // authData = map[string]interface{}{
"type": "ldap", // "type": "ldap",
"ldap": map[string]interface{}{ // "ldap": map[string]interface{}{
"addr": "192.168.8.12:389", // "addr": "192.168.8.12:389",
"tls": true, // "tls": true,
"bind_name": "userfind@abc.com", // "bind_name": "userfind@abc.com",
"bind_pwd": "afdbfdsafds", // "bind_pwd": "afdbfdsafds",
"base_dn": "dc=abc,dc=com", // "base_dn": "dc=abc,dc=com",
"object_class": "person", // "object_class": "person",
"search_attr": "sAMAccountName", // "search_attr": "sAMAccountName",
"member_of": "cn=vpn,cn=user,dc=abc,dc=com", // "member_of": "cn=vpn,cn=user,dc=abc,dc=com",
}, // },
} // }
g3 := Group{Name: group3, Status: 1, ClientDns: dns, RouteInclude: route, Auth: authData} // g3 := Group{Name: group3, Status: 1, ClientDns: dns, RouteInclude: route, Auth: authData}
err = SetGroup(&g3) // err = SetGroup(&g3)
ast.Nil(err) // ast.Nil(err)
err = CheckUser("aaa", "bbbbbbb", group3) // err = CheckUser("aaa", "bbbbbbb", group3)
if ast.NotNil(err) { // if ast.NotNil(err) {
ast.Equal("aaa LDAP服务器连接异常, 请检测服务器和端口", err.Error()) // ast.Equal("aaa LDAP服务器连接异常, 请检测服务器和端口", err.Error())
} // }
} }

View File

@ -1,121 +0,0 @@
package handler
import (
"context"
"encoding/xml"
"io"
"net"
"net/http"
"strings"
"time"
"github.com/bjdgyc/anylink/base"
)
// var lockManager = admin.GetLockManager()
const loginStatusKey = "login_status"
type HttpContext struct {
LoginStatus bool // 登录状态
}
// 防爆破中间件
func antiBruteForce(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, old_r *http.Request) {
// 防爆破功能全局开关
if !base.Cfg.AntiBruteForce {
next.ServeHTTP(w, old_r)
return
}
// 非并发安全
hc := &HttpContext{}
ctx := context.WithValue(context.Background(), loginStatusKey, hc)
r := old_r.WithContext(ctx)
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request body", http.StatusBadRequest)
return
}
defer r.Body.Close()
cr := ClientRequest{}
err = xml.Unmarshal(body, &cr)
if err != nil {
http.Error(w, "Failed to parse XML", http.StatusBadRequest)
return
}
username := cr.Auth.Username
if r.URL.Path == "/otp-verification" {
sessionID, err := GetCookie(r, "auth-session-id")
if err != nil {
http.Error(w, "Invalid session, please login again", http.StatusUnauthorized)
return
}
sessionData, err := SessStore.GetAuthSession(sessionID)
if err != nil {
http.Error(w, "Invalid session, please login again", http.StatusUnauthorized)
return
}
username = sessionData.ClientRequest.Auth.Username
}
ip, _, err := net.SplitHostPort(r.RemoteAddr) // 提取纯 IP 地址,去掉端口号
if err != nil {
http.Error(w, "Unable to parse IP address", http.StatusInternalServerError)
return
}
now := time.Now()
// 检查IP是否在白名单中
if lockManager.IsWhitelisted(ip) {
r.Body = io.NopCloser(strings.NewReader(string(body)))
next.ServeHTTP(w, r)
return
}
// 检查全局 IP 锁定
if base.Cfg.MaxGlobalIPBanCount > 0 && lockManager.CheckGlobalIPLock(ip, now) {
base.Warn("IP", ip, "is globally locked. Try again later.")
http.Error(w, "Account globally locked due to too many failed attempts. Try again later.", http.StatusTooManyRequests)
return
}
// 检查全局用户锁定
if base.Cfg.MaxGlobalUserBanCount > 0 && lockManager.CheckGlobalUserLock(username, now) {
base.Warn("User", username, "is globally locked. Try again later.")
http.Error(w, "Account globally locked due to too many failed attempts. Try again later.", http.StatusTooManyRequests)
return
}
// 检查单个用户的 IP 锁定
if base.Cfg.MaxBanCount > 0 && lockManager.CheckUserIPLock(username, ip, now) {
base.Warn("IP", ip, "is locked for user", username, "Try again later.")
http.Error(w, "Account locked due to too many failed attempts. Try again later.", http.StatusTooManyRequests)
return
}
// 重新设置请求体以便后续处理器可以访问
r.Body = io.NopCloser(strings.NewReader(string(body)))
// 调用下一个处理器
next.ServeHTTP(w, r)
// 检查登录状态
// Status, _ := lockManager.LoginStatus.Load(loginStatusKey)
// loginStatus, _ := Status.(bool)
loginStatus := hc.LoginStatus
// 更新用户登录状态
lockManager.UpdateGlobalIPLock(ip, now, loginStatus)
lockManager.UpdateGlobalUserLock(username, now, loginStatus)
lockManager.UpdateUserIPLock(username, ip, now, loginStatus)
// 清除登录状态
// lockManager.LoginStatus.Delete(loginStatusKey)
})
}

View File

@ -102,9 +102,6 @@ func LinkAuth(w http.ResponseWriter, r *http.Request) {
ext := map[string]interface{}{"mac_addr": cr.MacAddressList.MacAddress} ext := map[string]interface{}{"mac_addr": cr.MacAddressList.MacAddress}
err = dbdata.CheckUser(cr.Auth.Username, cr.Auth.Password, cr.GroupSelect, ext) err = dbdata.CheckUser(cr.Auth.Username, cr.Auth.Password, cr.GroupSelect, ext)
if err != nil { if err != nil {
// lockManager.LoginStatus.Store(loginStatusKey, false) // 记录登录失败状态
// hc := r.Context().Value(loginStatusKey).(*HttpContext)
// hc.LoginStatus = false
lockManager.UpdateLoginStatus(cr.Auth.Username, r.RemoteAddr, false) // 记录登录失败状态 lockManager.UpdateLoginStatus(cr.Auth.Username, r.RemoteAddr, false) // 记录登录失败状态
base.Warn(err, r.RemoteAddr) base.Warn(err, r.RemoteAddr)
@ -131,9 +128,6 @@ func LinkAuth(w http.ResponseWriter, r *http.Request) {
} }
// 用户otp验证 // 用户otp验证
if base.Cfg.AuthAloneOtp && !v.DisableOtp { if base.Cfg.AuthAloneOtp && !v.DisableOtp {
// lockManager.LoginStatus.Store(loginStatusKey, true) // 重置OTP验证计数
// hc := r.Context().Value(loginStatusKey).(*HttpContext)
// hc.LoginStatus = true
lockManager.UpdateLoginStatus(cr.Auth.Username, r.RemoteAddr, true) // 重置OTP验证计数 lockManager.UpdateLoginStatus(cr.Auth.Username, r.RemoteAddr, true) // 重置OTP验证计数
sessionID, err := GenerateSessionID() sessionID, err := GenerateSessionID()

View File

@ -111,9 +111,6 @@ func DeleteCookie(w http.ResponseWriter, name string) {
http.SetCookie(w, cookie) http.SetCookie(w, cookie)
} }
func CreateSession(w http.ResponseWriter, r *http.Request, authSession *AuthSession) { func CreateSession(w http.ResponseWriter, r *http.Request, authSession *AuthSession) {
// lockManager.LoginStatus.Store(loginStatusKey, true) // 更新登录成功状态
// hc := r.Context().Value(loginStatusKey).(*HttpContext)
// hc.LoginStatus = true
cr := authSession.ClientRequest cr := authSession.ClientRequest
ua := authSession.UserActLog ua := authSession.UserActLog
@ -208,14 +205,6 @@ func LinkAuth_otp(w http.ResponseWriter, r *http.Request) {
// 动态码错误 // 动态码错误
if !dbdata.CheckOtp(username, otp, otpSecret) { if !dbdata.CheckOtp(username, otp, otpSecret) {
// if sessionData.AddOtpErrCount(1) > maxOtpErrCount {
// SessStore.DeleteAuthSession(sessionID)
// http.Error(w, "TooManyError, please login again", http.StatusBadRequest)
// return
// }
// lockManager.LoginStatus.Store(loginStatusKey, false) // 记录登录失败状态
// hc := r.Context().Value(loginStatusKey).(*HttpContext)
// hc.LoginStatus = false
lockManager.UpdateLoginStatus(username, r.RemoteAddr, false) // 记录登录失败状态 lockManager.UpdateLoginStatus(username, r.RemoteAddr, false) // 记录登录失败状态
base.Warn("OTP 动态码错误", username, r.RemoteAddr) base.Warn("OTP 动态码错误", username, r.RemoteAddr)