169 lines
4.4 KiB
Go
169 lines
4.4 KiB
Go
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
|
||
}
|