mirror of
https://github.com/bjdgyc/anylink.git
synced 2025-09-09 01:21:23 +08:00
修复证书验证没有传入用户组的Bug
This commit is contained in:
@@ -131,6 +131,11 @@ func GenerateClientCert(w http.ResponseWriter, r *http.Request) {
|
||||
RespError(w, RespInternalErr, "用户名不能为空")
|
||||
return
|
||||
}
|
||||
groupname := r.FormValue("group_name")
|
||||
if groupname == "" {
|
||||
RespError(w, RespInternalErr, "用户组不能为空")
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户是否存在
|
||||
user := &dbdata.User{}
|
||||
@@ -141,7 +146,7 @@ func GenerateClientCert(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 生成客户端证书
|
||||
certData, err := dbdata.GenerateClientCert(username)
|
||||
certData, err := dbdata.GenerateClientCert(username, groupname)
|
||||
if err != nil {
|
||||
RespError(w, RespInternalErr, fmt.Sprintf("证书生成失败: %v", err))
|
||||
return
|
||||
@@ -305,3 +310,46 @@ func GetClientCertList(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
RespSucess(w, data)
|
||||
}
|
||||
|
||||
// UserCertInfo 获取用户证书生成所需信息
|
||||
func UserCertInfo(w http.ResponseWriter, r *http.Request) {
|
||||
_ = r.ParseForm()
|
||||
|
||||
// 获取所有启用的用户
|
||||
var users []dbdata.User
|
||||
err := dbdata.Find(&users, 1000, 1)
|
||||
if err != nil && !dbdata.CheckErrNotFound(err) {
|
||||
RespError(w, RespInternalErr, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取所有启用的组
|
||||
var groups []dbdata.Group
|
||||
err = dbdata.Find(&groups, 1000, 1)
|
||||
if err != nil && !dbdata.CheckErrNotFound(err) {
|
||||
RespError(w, RespInternalErr, err)
|
||||
return
|
||||
}
|
||||
|
||||
// 过滤启用的用户和组
|
||||
activeUsers := make([]dbdata.User, 0)
|
||||
for _, user := range users {
|
||||
if user.Status == 1 {
|
||||
activeUsers = append(activeUsers, user)
|
||||
}
|
||||
}
|
||||
|
||||
activeGroups := make([]dbdata.Group, 0)
|
||||
for _, group := range groups {
|
||||
if group.Status == 1 {
|
||||
activeGroups = append(activeGroups, group)
|
||||
}
|
||||
}
|
||||
|
||||
data := map[string]any{
|
||||
"users": activeUsers,
|
||||
"groups": activeGroups,
|
||||
}
|
||||
|
||||
RespSucess(w, data)
|
||||
}
|
||||
|
@@ -67,6 +67,7 @@ func StartAdmin() {
|
||||
// r.HandleFunc("/set/client_cert/enable", EnableClientCert)
|
||||
// r.HandleFunc("/set/client_cert/disable", DisableClientCert)
|
||||
r.HandleFunc("/set/client_cert/delete", DeleteClientCert)
|
||||
r.HandleFunc("/set/client_cert/user_cert_info", UserCertInfo)
|
||||
|
||||
r.HandleFunc("/user/list", UserList)
|
||||
r.HandleFunc("/user/detail", UserDetail)
|
||||
|
@@ -21,9 +21,9 @@ import (
|
||||
|
||||
// 客户端证书数据结构
|
||||
type ClientCertData struct {
|
||||
Id int `json:"id" xorm:"pk autoincr not null"`
|
||||
Username string `json:"username" xorm:"varchar(60) not null"`
|
||||
// GroupName string `json:"group_name" xorm:"varchar(60)"`
|
||||
Id int `json:"id" xorm:"pk autoincr not null"`
|
||||
Username string `json:"username" xorm:"varchar(60) not null"`
|
||||
GroupName string `json:"groupname" xorm:"varchar(60)"`
|
||||
Certificate string `json:"certificate" xorm:"text not null"`
|
||||
PrivateKey string `json:"private_key" xorm:"text not null"`
|
||||
SerialNumber string `json:"serial_number" xorm:"varchar(100) not null"`
|
||||
@@ -177,7 +177,7 @@ func GenerateClientCA() error {
|
||||
}
|
||||
|
||||
// 生成客户端证书并保存到数据库
|
||||
func GenerateClientCert(username string) (*ClientCertData, error) {
|
||||
func GenerateClientCert(username, groupname string) (*ClientCertData, error) {
|
||||
// 检查是否已存在证书记录
|
||||
_, err := GetClientCert(username)
|
||||
if err != nil {
|
||||
@@ -204,11 +204,12 @@ func GenerateClientCert(username string) (*ClientCertData, error) {
|
||||
template := x509.Certificate{
|
||||
SerialNumber: big.NewInt(time.Now().UnixNano()),
|
||||
Subject: pkix.Name{
|
||||
CommonName: username,
|
||||
Organization: []string{"AnyLink VPN"},
|
||||
Country: []string{"CN"},
|
||||
Province: []string{"Beijing"},
|
||||
Locality: []string{"Beijing"},
|
||||
CommonName: username,
|
||||
OrganizationalUnit: []string{groupname},
|
||||
Organization: []string{"AnyLink VPN"},
|
||||
Country: []string{"CN"},
|
||||
Province: []string{"Beijing"},
|
||||
Locality: []string{"Beijing"},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * 365), // 1年有效期
|
||||
@@ -232,6 +233,7 @@ func GenerateClientCert(username string) (*ClientCertData, error) {
|
||||
// 保存到数据库
|
||||
clientCertData := &ClientCertData{
|
||||
Username: username,
|
||||
GroupName: groupname,
|
||||
Certificate: string(certPEM),
|
||||
PrivateKey: string(keyPEM),
|
||||
SerialNumber: template.SerialNumber.String(),
|
||||
@@ -319,6 +321,11 @@ func ValidateClientCert(cert *x509.Certificate, userAgent string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if clientCertData.GroupName != cert.Subject.OrganizationalUnit[0] {
|
||||
base.Error("证书验证失败:证书组名与用户组名不匹配")
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查证书状态
|
||||
if clientCertData.GetStatus() != CertStatusActive {
|
||||
base.Error("证书验证失败:证书状态为", clientCertData.GetStatusText())
|
||||
|
@@ -81,13 +81,22 @@ func LinkAuth(w http.ResponseWriter, r *http.Request) {
|
||||
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
|
||||
clientCert := r.TLS.PeerCertificates[0]
|
||||
username := clientCert.Subject.CommonName
|
||||
groupname := clientCert.Subject.OrganizationalUnit[0]
|
||||
if username == "" || groupname == "" {
|
||||
base.Warn("客户端证书缺少用户名或组名")
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证证书有效性和用户状态
|
||||
if dbdata.ValidateClientCert(clientCert, userAgent) {
|
||||
// 证书认证成功,创建会话
|
||||
base.Info("用户通过证书认证:", username)
|
||||
|
||||
sessionData.ClientRequest.GroupSelect = groupname
|
||||
sessionData.ClientRequest.Auth.Username = username
|
||||
ua.Username = username
|
||||
ua.GroupName = groupname
|
||||
ua.Info = "用户通过证书认证登录"
|
||||
ua.Status = dbdata.UserConnected
|
||||
dbdata.UserActLogIns.Add(*ua, userAgent)
|
||||
|
Reference in New Issue
Block a user