mirror of
https://github.com/bjdgyc/anylink.git
synced 2025-09-06 05:16:54 +08:00
增加证书认证开关,优化前端下载证书的错误处理
This commit is contained in:
@@ -47,6 +47,7 @@ type ServerConfig struct {
|
||||
DbSource string `json:"db_source"`
|
||||
CertFile string `json:"cert_file"`
|
||||
CertKey string `json:"cert_key"`
|
||||
AuthAloneCert bool `json:"auth_alone_cert"`
|
||||
ClientCertCAFile string `json:"client_ca_file"`
|
||||
ClientCertCAKeyFile string `json:"client_ca_key_file"`
|
||||
FilesPath string `json:"files_path"`
|
||||
|
@@ -33,6 +33,7 @@ var configs = []config{
|
||||
{Typ: cfgStr, Name: "db_source", Usage: "数据库source", ValStr: "./conf/anylink.db"},
|
||||
{Typ: cfgStr, Name: "cert_file", Usage: "证书文件", ValStr: "./conf/vpn_cert.pem"},
|
||||
{Typ: cfgStr, Name: "cert_key", Usage: "证书密钥", ValStr: "./conf/vpn_cert.key"},
|
||||
{Typ: cfgBool, Name: "auth_alone_cert", Usage: "启用独立证书验证", ValBool: false},
|
||||
{Typ: cfgStr, Name: "client_ca_file", Usage: "客户端证书CA证书", ValStr: "./conf/client_ca.pem"},
|
||||
{Typ: cfgStr, Name: "client_ca_key_file", Usage: "客户端证书CA密钥", ValStr: "./conf/client_ca.key"},
|
||||
{Typ: cfgStr, Name: "files_path", Usage: "外部下载文件路径", ValStr: "./conf/files"},
|
||||
|
@@ -9,6 +9,16 @@ db_source = "./conf/anylink.db"
|
||||
#证书文件 使用跟nginx一样的证书即可
|
||||
cert_file = "./conf/vpn_cert.pem"
|
||||
cert_key = "./conf/vpn_cert.key"
|
||||
|
||||
#是否启用独立证书验证,开启后客户端连接需要携带证书
|
||||
#如果不开启则使用用户名密码验证
|
||||
auth_alone_cert = false
|
||||
|
||||
#客户端证书CA证书
|
||||
client_cert_ca_file = "./conf/client_ca.pem"
|
||||
#客户端证书CA密钥
|
||||
client_cert_ca_key_file = "./conf/client_ca.key"
|
||||
|
||||
files_path = "./conf/files"
|
||||
profile = "./conf/profile.xml"
|
||||
#profile name(用于区分不同服务端的配置)
|
||||
@@ -52,7 +62,7 @@ admin_addr = ":8800"
|
||||
proxy_protocol = false
|
||||
|
||||
#开启go标准库http.Server的日志
|
||||
http_server_log=false
|
||||
http_server_log = false
|
||||
|
||||
#虚拟网络类型[tun macvtap tap]
|
||||
link_mode = "tun"
|
||||
|
@@ -11,11 +11,6 @@ cert_file = "./conf/vpn_cert.pem"
|
||||
cert_key = "./conf/vpn_cert.key"
|
||||
files_path = "./conf/files"
|
||||
|
||||
#客户端证书CA证书
|
||||
client_cert_ca_file = "./conf/client_ca.pem"
|
||||
#客户端证书CA密钥
|
||||
client_cert_ca_key_file = "./conf/client_ca.key"
|
||||
|
||||
#日志目录,默认为空写入标准输出
|
||||
#log_path = "./log"
|
||||
log_level = "debug"
|
||||
|
@@ -78,32 +78,43 @@ func LinkAuth(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
// 检查客户端证书认证
|
||||
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
|
||||
if base.Cfg.AuthAloneCert {
|
||||
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
|
||||
}
|
||||
ua.Username = username
|
||||
ua.GroupName = groupname
|
||||
ua.Info = "用户通过证书认证登录"
|
||||
ua.Status = dbdata.UserConnected
|
||||
dbdata.UserActLogIns.Add(*ua, userAgent)
|
||||
// 验证证书有效性和用户状态
|
||||
if dbdata.ValidateClientCert(clientCert, userAgent) {
|
||||
// 证书认证成功,创建会话
|
||||
base.Info("用户通过证书认证:", username)
|
||||
|
||||
CreateSession(w, r, sessionData)
|
||||
return
|
||||
sessionData.ClientRequest.GroupSelect = groupname
|
||||
sessionData.ClientRequest.Auth.Username = username
|
||||
ua.Info = "用户通过证书认证登录"
|
||||
ua.Status = dbdata.UserConnected
|
||||
dbdata.UserActLogIns.Add(*ua, userAgent)
|
||||
|
||||
CreateSession(w, r, sessionData)
|
||||
return
|
||||
} else {
|
||||
ua.Info = "客户端证书验证失败"
|
||||
ua.Status = dbdata.UserAuthFail
|
||||
dbdata.UserActLogIns.Add(*ua, userAgent)
|
||||
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
}
|
||||
base.Warn("启用了独立证书验证,但用户未提供有效证书")
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
if cr.Type == "init" {
|
||||
|
@@ -66,13 +66,16 @@ func startTls() {
|
||||
NextProtos: []string{"http/1.1"},
|
||||
MinVersion: tls.VersionTLS12,
|
||||
CipherSuites: selectedCipherSuites,
|
||||
ClientAuth: tls.VerifyClientCertIfGiven, // 验证客户端证书
|
||||
ClientCAs: dbdata.LoadClientCAPool(), // 加载客户端CA证书
|
||||
GetCertificate: func(chi *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
base.Trace("GetCertificate ServerName", chi.ServerName)
|
||||
return dbdata.GetCertificateBySNI(chi.ServerName)
|
||||
},
|
||||
}
|
||||
// 开启证书认证
|
||||
if base.Cfg.AuthAloneCert {
|
||||
tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven // 验证客户端证书
|
||||
tlsConfig.ClientCAs = dbdata.LoadClientCAPool() // 加载客户端CA证书
|
||||
}
|
||||
srv := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: initRoute(),
|
||||
|
@@ -561,6 +561,20 @@ export default {
|
||||
url: '/set/client_cert/download?' + params.toString(),
|
||||
responseType: 'blob'
|
||||
}).then(response => {
|
||||
const contentType = response.headers['content-type'];
|
||||
if (contentType && contentType.includes('application/json')) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
try {
|
||||
const errorData = JSON.parse(reader.result);
|
||||
this.$message.error(errorData.msg || '证书下载失败');
|
||||
} catch (e) {
|
||||
this.$message.error('证书下载失败');
|
||||
}
|
||||
};
|
||||
reader.readAsText(response.data);
|
||||
return;
|
||||
}
|
||||
const blob = new Blob([response.data], { type: 'application/x-pkcs12' });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
@@ -572,8 +586,8 @@ export default {
|
||||
window.URL.revokeObjectURL(url);
|
||||
this.$message.success('证书下载成功');
|
||||
}).catch(error => {
|
||||
if (error.response && error.response.data && error.response.data.msg) {
|
||||
this.$message.error(error.response.data.msg);
|
||||
if (error.response && error.response.data) {
|
||||
this.$message.error(error.response.data.msg || '证书下载失败');
|
||||
} else {
|
||||
this.$message.error('证书下载失败');
|
||||
}
|
||||
|
Reference in New Issue
Block a user