rdpgw/cmd/auth/database/apidb.go
jiangcuo 7ac73b9489
Some checks failed
CodeQL / Analyze (go) (push) Has been cancelled
Docker Image CI / build (push) Has been cancelled
Go / Build (push) Has been cancelled
增加服务端验证
2025-04-01 22:12:24 +08:00

169 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package database
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"net/url"
)
// ApiDb 结构实现Database接口通过API验证用户凭据
type ApiDb struct {
ApiUrl string // API URL模板使用{username}和{password}作为占位符
}
// NewApiDb 创建一个新的ApiDb实例
func NewApiDb(apiUrl string) *ApiDb {
return &ApiDb{
ApiUrl: apiUrl,
}
}
// GetPassword 从API获取用户密码
// 这个方法会调用API来获取用户的实际密码用于NTLM认证
func (a *ApiDb) GetPassword(username string) string {
log.Printf("Getpassword: %s", username)
// 如果用户名为空,直接返回失败
if username == "" {
log.Printf("API password retrieval failed: empty username")
return ""
}
// 构建API URL替换占位符
apiUrl := a.ApiUrl
// 构建完整的URL包括查询参数 - 使用getpassword模式
fullUrl := fmt.Sprintf("%s?username=%s&mode=getpassword",
apiUrl, url.QueryEscape(username))
log.Printf("Sending API password request to: %s", fullUrl)
// 创建自定义HTTP客户端跳过SSL证书验证
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
// 发送请求到API使用不验证SSL证书的客户端
resp, err := client.Get(fullUrl)
if err != nil {
log.Printf("API password retrieval error: %v", err)
return ""
}
defer resp.Body.Close()
// 检查HTTP状态码
if resp.StatusCode != http.StatusOK {
log.Printf("API password retrieval failed with status: %d", resp.StatusCode)
return ""
}
// 读取响应内容
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Failed to read API response: %v", err)
return ""
}
log.Printf("API password response received")
// 解析响应
var result struct {
Status string `json:"status"`
Password string `json:"password"`
}
err = json.NewDecoder(bytes.NewReader(body)).Decode(&result)
if err != nil {
log.Printf("Failed to parse API response: %v", err)
return ""
}
// 检查响应内容
if result.Status != "success" || result.Password == "" {
log.Printf("API did not return a valid password for user: %s", username)
return ""
}
log.Printf("API password retrieval successful for user: %s", username)
return result.Password
}
// VerifyCredentials 验证用户凭据
func (a *ApiDb) VerifyCredentials(username, password string) bool {
// 如果用户名为空,直接返回失败
if username == "" {
log.Printf("API verification failed: empty username")
return false
}
// 构建API URL替换占位符
apiUrl := a.ApiUrl
// 构建完整的URL包括查询参数
var fullUrl string
if password == "" {
// NTLM场景下直接将用户名传递给API
// 这种情况下后端API应当能够独立验证用户
fullUrl = fmt.Sprintf("%s?username=%s&mode=verify",
apiUrl, url.QueryEscape(username))
log.Printf("Verifying NTLM user via API: %s", username)
} else {
// 常规场景
fullUrl = fmt.Sprintf("%s?username=%s&password=%s&mode=verify",
apiUrl, url.QueryEscape(username), url.QueryEscape(password))
}
log.Printf("Sending API verification request to: %s", fullUrl)
// 创建自定义HTTP客户端跳过SSL证书验证
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
// 发送请求到API使用不验证SSL证书的客户端
resp, err := client.Get(fullUrl)
if err != nil {
log.Printf("API verification error: %v", err)
return false
}
defer resp.Body.Close()
// 检查HTTP状态码
if resp.StatusCode != http.StatusOK {
log.Printf("API verification failed with status: %d", resp.StatusCode)
return false
}
// 读取响应内容
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Printf("Failed to read API response: %v", err)
return false
}
log.Printf("API response: %s", string(body))
// 解析响应
var result map[string]interface{}
err = json.NewDecoder(bytes.NewReader(body)).Decode(&result)
if err != nil {
log.Printf("Failed to parse API response: %v", err)
return false
}
// 检查响应内容
// 如果响应包含"success",则验证成功
if status, ok := result["status"].(string); ok && status == "success" {
log.Printf("API verification successful for user: %s", username)
return true
}
// 如果没有找到预期的成功标识,则验证失败
log.Printf("API verification failed for user: %s", username)
return false
}