版本封存
This commit is contained in:
@@ -2,14 +2,15 @@ package services
|
||||
|
||||
import (
|
||||
models2 "cmii-uav-watchdog-common/models"
|
||||
"cmii-uav-watchdog-common/totp_tier_one"
|
||||
"cmii-uav-watchdog-common/totp_tier_two"
|
||||
"cmii-uav-watchdog-common/utils"
|
||||
"cmii-uav-watchdog-common/wdd_log"
|
||||
"cmii-uav-watchdog/config"
|
||||
"cmii-uav-watchdog/utils"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 单例相关变量
|
||||
@@ -21,11 +22,11 @@ var (
|
||||
|
||||
// AuthService 授权服务
|
||||
type AuthService struct {
|
||||
mu sync.RWMutex
|
||||
hostInfoSet map[string]models2.HostInfo // 主机信息集合
|
||||
authorizationInfo models2.AuthorizationStorage // 授权信息
|
||||
totpService *TOTPService
|
||||
initialized bool
|
||||
mu sync.RWMutex
|
||||
heartBeatHostInfoMap map[string]models2.HostInfo // 主机信息集合
|
||||
authorizationInfo *models2.AuthorizationStorage // 授权信息
|
||||
totpService *TOTPService
|
||||
initialized bool
|
||||
}
|
||||
|
||||
// NewAuthService 创建授权服务(单例模式)
|
||||
@@ -42,20 +43,25 @@ func NewAuthService() *AuthService {
|
||||
|
||||
// 创建新实例
|
||||
service := &AuthService{
|
||||
hostInfoSet: make(map[string]models2.HostInfo),
|
||||
totpService: NewTOTPService(),
|
||||
initialized: false,
|
||||
heartBeatHostInfoMap: make(map[string]models2.HostInfo),
|
||||
totpService: NewTOTPService(),
|
||||
initialized: false,
|
||||
}
|
||||
|
||||
// 尝试从本地加载授权信息
|
||||
service.loadAuthorizationInfo()
|
||||
|
||||
// 确保 authorizationInfo 不为 nil
|
||||
if service.authorizationInfo == nil {
|
||||
service.authorizationInfo = &models2.AuthorizationStorage{}
|
||||
}
|
||||
|
||||
// 判断 项目级别的 TOTP密钥是否为空
|
||||
// 若为空 则生成一个 二级TOTP密钥 然后持久化写入到授权文件中
|
||||
if service.authorizationInfo.SecondTOTPSecret == "" {
|
||||
secondTOTPSecret, err := service.totpService.GenerateTierTwoTOTPSecret()
|
||||
secondTOTPSecret, err := totp_tier_two.GenerateTierTwoTOTPSecret()
|
||||
if err != nil {
|
||||
log.Printf("生成二级TOTP密钥失败: %v", err)
|
||||
wdd_log.Error("生成二级TOTP密钥失败: %v", err)
|
||||
return
|
||||
}
|
||||
service.authorizationInfo.SecondTOTPSecret = secondTOTPSecret
|
||||
@@ -63,7 +69,7 @@ func NewAuthService() *AuthService {
|
||||
// 持久化写入到授权文件中
|
||||
err = service.saveAuthorizationInfo()
|
||||
if err != nil {
|
||||
log.Printf("持久化写入授权文件失败: %v", err)
|
||||
wdd_log.Error("持久化写入授权文件失败: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -80,8 +86,13 @@ func (as *AuthService) AddHostInfo(hostInfo models2.HostInfo) {
|
||||
as.mu.Lock()
|
||||
defer as.mu.Unlock()
|
||||
|
||||
hostKey := utils.GenerateHostKey(hostInfo)
|
||||
as.hostInfoSet[hostKey] = hostInfo
|
||||
hostKey, err := totp_tier_one.EncryptHostInfo(hostInfo, as.totpService.tierOneSecret)
|
||||
if err != nil {
|
||||
wdd_log.Error("加密主机信息失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
as.heartBeatHostInfoMap[hostKey] = hostInfo
|
||||
}
|
||||
|
||||
// GenerateAuthorizationFile 生成授权文件
|
||||
@@ -90,96 +101,143 @@ func (as *AuthService) GenerateAuthorizationFile() (*models2.AuthorizationFile,
|
||||
defer as.mu.RUnlock()
|
||||
|
||||
// 检查是否有主机信息
|
||||
if len(as.hostInfoSet) == 0 {
|
||||
if len(as.heartBeatHostInfoMap) == 0 {
|
||||
return nil, errors.New("没有可用的主机信息")
|
||||
}
|
||||
|
||||
// 生成TOTP验证码
|
||||
totpCode, err := as.totpService.GenerateTierTwoTOTPCode(as.authorizationInfo.SecondTOTPSecret)
|
||||
// 加密主机信息
|
||||
encryptedHostMap := make(map[string]models2.HostInfo)
|
||||
for _, hostInfo := range as.heartBeatHostInfoMap {
|
||||
encrypted, err := totp_tier_one.EncryptHostInfo(hostInfo, as.totpService.tierOneSecret)
|
||||
if err != nil {
|
||||
wdd_log.Error("加密主机信息失败: %v hostInfo NetworkInfo: %v", err, hostInfo.NetInfo)
|
||||
}
|
||||
encryptedHostMap[encrypted] = hostInfo
|
||||
}
|
||||
|
||||
// 获取项目命名空间
|
||||
projectNamespace := config.GetConfig().Project.ProjectNamespace
|
||||
encryptedNamespace, err := totp_tier_one.Encrypt(projectNamespace, projectNamespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
|
||||
// 准备初次授权时间
|
||||
firstAuthTime := now
|
||||
if as.initialized {
|
||||
firstAuthTime = as.authorizationInfo.FirstAuthTime
|
||||
}
|
||||
|
||||
// 计算时间偏移
|
||||
timeOffset := now.Unix() - firstAuthTime.Unix()
|
||||
|
||||
// 加密主机信息
|
||||
encryptedHosts := make([]string, 0)
|
||||
for _, hostInfo := range as.hostInfoSet {
|
||||
encrypted, err := utils.EncryptHostInfo(hostInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
encryptedHosts = append(encryptedHosts, encrypted)
|
||||
// 生成TOTP验证码
|
||||
tierOneSecret := config.GetConfig().TierOneAuth.TierOneSecret
|
||||
tierOneTOTPCode, err := totp_tier_one.GenerateTierOneTOTPCode(tierOneSecret)
|
||||
if err != nil {
|
||||
wdd_log.Error("生成TOTP验证码失败: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建授权文件
|
||||
authFile := &models2.AuthorizationFile{
|
||||
EncryptedHosts: encryptedHosts,
|
||||
TOTPCode: totpCode,
|
||||
CurrentTime: now,
|
||||
FirstAuthTime: firstAuthTime,
|
||||
TimeOffset: timeOffset,
|
||||
EncryptedHostMap: encryptedHostMap,
|
||||
TOTPCode: tierOneTOTPCode,
|
||||
CurrentTime: utils.CurentTimeString(),
|
||||
ProjectNamespace: projectNamespace,
|
||||
EncryptedNamespace: encryptedNamespace,
|
||||
}
|
||||
|
||||
return authFile, nil
|
||||
}
|
||||
|
||||
// ProcessAuthorizationCode 处理授权码
|
||||
func (as *AuthService) ProcessAuthorizationCode(code models2.AuthorizationCode) error {
|
||||
func (as *AuthService) ProcessAuthorizationCode(authCode models2.AuthorizationCode) error {
|
||||
as.mu.Lock()
|
||||
defer as.mu.Unlock()
|
||||
|
||||
// 验证TOTP
|
||||
if !as.totpService.VerifyTierTwoTOTPCode(code.TOTPCode, as.authorizationInfo.SecondTOTPSecret) {
|
||||
if !as.totpService.VerifyTierOneTOTP(authCode.TOTPCode) {
|
||||
wdd_log.Error("无效的授权码: TOTP验证失败")
|
||||
return errors.New("无效的授权码: TOTP验证失败")
|
||||
}
|
||||
|
||||
// 解密项目命名空间
|
||||
projectNamespace, err := totp_tier_one.Decrypt(authCode.EncryptedNamespace, authCode.ProjectNamespace)
|
||||
if err != nil {
|
||||
wdd_log.Error("解密项目命名空间失败: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 验证项目命名空间
|
||||
if projectNamespace != config.GetConfig().Project.ProjectNamespace {
|
||||
wdd_log.Error("无效的授权码: 项目命名空间不匹配")
|
||||
return errors.New("无效的授权码: 项目命名空间不匹配")
|
||||
}
|
||||
|
||||
// 解密服务器信息
|
||||
encryptedServerInfoMap := authCode.EncryptedHostMap
|
||||
serverInfoMap := make(map[string]models2.HostInfo)
|
||||
for encrypted, hostInfo := range encryptedServerInfoMap {
|
||||
isOK, err := totp_tier_one.DecryptHostInfo(encrypted, hostInfo, as.totpService.tierOneSecret)
|
||||
if !isOK || err != nil {
|
||||
wdd_log.Error("解密服务器信息失败: %v hostInfo NetworkInfo: %v", err, hostInfo.NetInfo)
|
||||
continue
|
||||
}
|
||||
// 将解密后的主机信息添加到serverInfoMap中
|
||||
serverInfoMap[encrypted] = hostInfo
|
||||
// 将解密后的主机信息添加到hostInfoSet中
|
||||
as.heartBeatHostInfoMap[encrypted] = hostInfo
|
||||
}
|
||||
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
now := utils.CurentTimeString()
|
||||
|
||||
// 准备初次授权时间
|
||||
firstAuthTime := now
|
||||
if as.initialized {
|
||||
firstAuthTime = as.authorizationInfo.FirstAuthTime
|
||||
if as.authorizationInfo.FirstAuthTime != "" {
|
||||
wdd_log.Debug("已存在初次授权时间: %s", as.authorizationInfo.FirstAuthTime)
|
||||
firstAuthTime = as.authorizationInfo.FirstAuthTime
|
||||
}
|
||||
}
|
||||
|
||||
// 计算授权时间偏移
|
||||
timeOffset := now.Unix() - code.CurrentTime.Unix()
|
||||
nowTime, err := utils.ParseTimeString(now)
|
||||
if err != nil {
|
||||
wdd_log.Error("解析当前时间失败: %v", err)
|
||||
return err
|
||||
}
|
||||
firstAuthTimeTime, err := utils.ParseTimeString(firstAuthTime)
|
||||
if err != nil {
|
||||
wdd_log.Error("解析初次授权时间失败: %v", err)
|
||||
return err
|
||||
}
|
||||
timeOffset := nowTime.Unix() - firstAuthTimeTime.Unix()
|
||||
|
||||
// 加密授权码
|
||||
authCodeJSON, err := json.Marshal(code)
|
||||
authCodeJSON, err := json.Marshal(authCode)
|
||||
if err != nil {
|
||||
wdd_log.Error("加密授权码失败: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
encryptedCode, err := utils.Encrypt(string(authCodeJSON), config.GetConfig().Auth.Secret)
|
||||
// 加密授权码 全部加密
|
||||
encryptedCode, err := totp_tier_one.Encrypt(string(authCodeJSON), as.totpService.tierOneSecret)
|
||||
if err != nil {
|
||||
wdd_log.Error("加密授权码失败: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 保存授权信息
|
||||
as.authorizationInfo = models2.AuthorizationStorage{
|
||||
EncryptedCode: encryptedCode,
|
||||
FirstAuthTime: firstAuthTime,
|
||||
TimeOffset: timeOffset,
|
||||
AuthorizedHosts: code.EncryptedHosts,
|
||||
as.authorizationInfo = &models2.AuthorizationStorage{
|
||||
EncryptedAuthrizationCode: encryptedCode,
|
||||
FirstAuthTime: firstAuthTime,
|
||||
TimeOffset: timeOffset,
|
||||
AuthorizedHostMap: serverInfoMap,
|
||||
SecondTOTPSecret: as.authorizationInfo.SecondTOTPSecret,
|
||||
ProjectNamespace: projectNamespace,
|
||||
EncryptedNamespace: authCode.EncryptedNamespace,
|
||||
}
|
||||
|
||||
// 保存到文件
|
||||
if err := as.saveAuthorizationInfo(); err != nil {
|
||||
wdd_log.Error("保存授权信息失败: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 设置初始化状态
|
||||
as.initialized = true
|
||||
|
||||
return nil
|
||||
@@ -195,19 +253,14 @@ func (as *AuthService) IsHostAuthorized(hostInfo models2.HostInfo) bool {
|
||||
}
|
||||
|
||||
// 加密主机信息
|
||||
encrypted, err := utils.EncryptHostInfo(hostInfo)
|
||||
encrypted, err := totp_tier_one.EncryptHostInfo(hostInfo, as.totpService.tierOneSecret)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查是否在已授权列表中
|
||||
for _, host := range as.authorizationInfo.AuthorizedHosts {
|
||||
if host == encrypted {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
_, ok := as.authorizationInfo.AuthorizedHostMap[encrypted]
|
||||
return ok
|
||||
}
|
||||
|
||||
// VerifyAuthorizationTime 验证授权时间有效性
|
||||
@@ -220,43 +273,87 @@ func (as *AuthService) VerifyAuthorizationTime() {
|
||||
}
|
||||
|
||||
// 获取当前时间和存储的初次授权时间
|
||||
now := time.Now()
|
||||
now := utils.CurentTimeString()
|
||||
storedOffset := as.authorizationInfo.TimeOffset
|
||||
|
||||
nowTime, err := utils.ParseTimeString(now)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
firstAuthTime, err := utils.ParseTimeString(as.authorizationInfo.FirstAuthTime)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 计算实际时间偏移
|
||||
actualOffset := now.Unix() - as.authorizationInfo.FirstAuthTime.Unix()
|
||||
actualOffset := nowTime.Unix() - firstAuthTime.Unix()
|
||||
|
||||
// 计算偏差
|
||||
offsetDiff := actualOffset - storedOffset
|
||||
|
||||
// 获取允许的时间偏移
|
||||
allowedOffset := config.GetConfig().Auth.TimeOffsetAllowed
|
||||
allowedOffset := config.GetConfig().TierOneAuth.TimeOffsetAllowed
|
||||
|
||||
// 检查偏差是否超过允许范围
|
||||
if offsetDiff > allowedOffset || offsetDiff < -allowedOffset {
|
||||
log.Printf("检测到时间篡改! 存储偏移: %d, 实际偏移: %d, 差值: %d",
|
||||
wdd_log.Warn("检测到时间篡改! 存储偏移: %d, 实际偏移: %d, 差值: %d",
|
||||
storedOffset, actualOffset, offsetDiff)
|
||||
// 这里可以添加更多的处理逻辑,例如发送警告、禁用授权等
|
||||
}
|
||||
}
|
||||
|
||||
// GetAuthorizationInfo 获取授权信息
|
||||
func (as *AuthService) GetAuthorizationInfo() interface{} {
|
||||
func (as *AuthService) GetAuthorizationInfo() (models2.AuthorizationStorage, error) {
|
||||
as.mu.RLock()
|
||||
defer as.mu.RUnlock()
|
||||
|
||||
if !as.initialized {
|
||||
return map[string]interface{}{
|
||||
"authorized": false,
|
||||
"message": "未授权",
|
||||
}
|
||||
return models2.AuthorizationStorage{}, errors.New("未授权")
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"authorized": true,
|
||||
"authorized_hosts": len(as.authorizationInfo.AuthorizedHosts),
|
||||
"first_auth_time": as.authorizationInfo.FirstAuthTime,
|
||||
// 解密授权码
|
||||
decryptedCode, err := totp_tier_one.Decrypt(as.authorizationInfo.EncryptedAuthrizationCode, as.totpService.tierOneSecret)
|
||||
if err != nil {
|
||||
return models2.AuthorizationStorage{}, err
|
||||
}
|
||||
|
||||
// 解析授权码
|
||||
var authorizationInfo models2.AuthorizationStorage
|
||||
if err := json.Unmarshal([]byte(decryptedCode), &authorizationInfo); err != nil {
|
||||
return models2.AuthorizationStorage{}, err
|
||||
}
|
||||
|
||||
return authorizationInfo, nil
|
||||
}
|
||||
|
||||
// GetAllHostInfo 获取所有主机信息(心跳检测到的所有主机)
|
||||
func (as *AuthService) GetAllHostInfo() map[string]models2.HostInfo {
|
||||
as.mu.RLock()
|
||||
defer as.mu.RUnlock()
|
||||
|
||||
// 返回主机信息集合的副本
|
||||
result := make(map[string]models2.HostInfo, len(as.heartBeatHostInfoMap))
|
||||
for k, v := range as.heartBeatHostInfoMap {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// GetAllAuthorizedHosts 获取所有已授权的主机信息
|
||||
func (as *AuthService) GetAllAuthorizedHosts() map[string]models2.HostInfo {
|
||||
as.mu.RLock()
|
||||
defer as.mu.RUnlock()
|
||||
|
||||
if !as.initialized || as.authorizationInfo == nil {
|
||||
return make(map[string]models2.HostInfo)
|
||||
}
|
||||
|
||||
// 返回已授权主机信息的副本
|
||||
result := make(map[string]models2.HostInfo, len(as.authorizationInfo.AuthorizedHostMap))
|
||||
for k, v := range as.authorizationInfo.AuthorizedHostMap {
|
||||
result[k] = v
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// saveAuthorizationInfo 保存授权信息到文件
|
||||
@@ -266,30 +363,40 @@ func (as *AuthService) saveAuthorizationInfo() error {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.WriteFile(config.GetConfig().Auth.AuthFilePath, data, 0600)
|
||||
return os.WriteFile(config.GetConfig().TierOneAuth.LocalAuthFilePath, data, 0600)
|
||||
}
|
||||
|
||||
// loadAuthorizationInfo 从文件加载授权信息
|
||||
func (as *AuthService) loadAuthorizationInfo() {
|
||||
filePath := config.GetConfig().Auth.AuthFilePath
|
||||
filePath := config.GetConfig().TierOneAuth.LocalAuthFilePath
|
||||
|
||||
// 检查文件是否存在
|
||||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||||
// 初始化一个空的授权信息
|
||||
as.authorizationInfo = &models2.AuthorizationStorage{}
|
||||
return
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
log.Printf("读取授权文件失败: %v", err)
|
||||
wdd_log.Error("读取授权文件失败: %v", err)
|
||||
// 初始化一个空的授权信息
|
||||
as.authorizationInfo = &models2.AuthorizationStorage{}
|
||||
return
|
||||
}
|
||||
|
||||
var authInfo models2.AuthorizationStorage
|
||||
var authInfo *models2.AuthorizationStorage
|
||||
if err := json.Unmarshal(data, &authInfo); err != nil {
|
||||
log.Printf("解析授权文件失败: %v", err)
|
||||
wdd_log.Error("解析授权文件失败: %v", err)
|
||||
// 初始化一个空的授权信息
|
||||
as.authorizationInfo = &models2.AuthorizationStorage{}
|
||||
return
|
||||
}
|
||||
|
||||
if authInfo == nil {
|
||||
authInfo = &models2.AuthorizationStorage{}
|
||||
}
|
||||
|
||||
as.authorizationInfo = authInfo
|
||||
as.initialized = true
|
||||
}
|
||||
|
||||
36
cmii-uav-watchdog/services/cmii_service.go
Normal file
36
cmii-uav-watchdog/services/cmii_service.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"cmii-uav-watchdog-common/models"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CMIIService CMII服务
|
||||
type CMIIService struct {
|
||||
authService *AuthService
|
||||
}
|
||||
|
||||
// NewCMIIService 创建CMII服务
|
||||
func NewCMIIService() *CMIIService {
|
||||
return &CMIIService{
|
||||
authService: NewAuthService(),
|
||||
}
|
||||
}
|
||||
|
||||
// HandleHostInfo 处理主机信息
|
||||
func (cs *CMIIService) HandleHostInfo(c *gin.Context) {
|
||||
|
||||
// 获取主机信息
|
||||
hostInfo := cs.authService.GetAllHostInfo()
|
||||
|
||||
// 返回单纯的主机信息
|
||||
hostInfoList := make([]models.HostInfo, 0)
|
||||
for _, host := range hostInfo {
|
||||
hostInfoList = append(hostInfoList, host)
|
||||
}
|
||||
|
||||
// 返回主机信息
|
||||
c.JSON(http.StatusOK, hostInfoList)
|
||||
}
|
||||
@@ -2,8 +2,10 @@ package services
|
||||
|
||||
import (
|
||||
"cmii-uav-watchdog-common/models"
|
||||
"cmii-uav-watchdog-common/totp_tier_two"
|
||||
"cmii-uav-watchdog-common/utils"
|
||||
"cmii-uav-watchdog-common/wdd_log"
|
||||
"errors"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -30,6 +32,7 @@ func (hs *HeartbeatService) ProcessHeartbeat(req models.HeartbeatRequest) (*mode
|
||||
|
||||
secondTOTPSecret := hs.authService.authorizationInfo.SecondTOTPSecret
|
||||
if secondTOTPSecret == "" {
|
||||
wdd_log.Error("二级TOTP密钥为空")
|
||||
return nil, errors.New("二级TOTP密钥为空")
|
||||
}
|
||||
|
||||
@@ -47,12 +50,13 @@ func (hs *HeartbeatService) ProcessHeartbeat(req models.HeartbeatRequest) (*mode
|
||||
}
|
||||
|
||||
// 检查totp验证码是否有效
|
||||
if !hs.totpService.VerifyTierTwoTOTPCode(req.TOTPCode, secondTOTPSecret) {
|
||||
if !totp_tier_two.VerifyTierTwoTOTPCode(req.TOTPCode, secondTOTPSecret) {
|
||||
// 解析认证主机的相关信息
|
||||
|
||||
// 计算 请求时间与当前时间的时间差
|
||||
utils.CurentTimeUnix()
|
||||
diff := time.Now().Unix() - req.Timestamp
|
||||
log.Printf("心跳请求时间与当前时间的时间差: %d", diff)
|
||||
wdd_log.Error("TOTP验证失败!心跳请求时间与当前时间的时间差: %d", diff)
|
||||
|
||||
return nil, errors.New("无效的TOTP验证码,请检查系统时间是否正确!")
|
||||
}
|
||||
@@ -61,7 +65,7 @@ func (hs *HeartbeatService) ProcessHeartbeat(req models.HeartbeatRequest) (*mode
|
||||
authorized := hs.authService.IsHostAuthorized(req.HostInfo)
|
||||
|
||||
// 生成TOTP验证码
|
||||
totpCode, err := hs.totpService.GenerateTierTwoTOTPCode(secondTOTPSecret)
|
||||
totpCode, err := totp_tier_two.GenerateTierTwoTOTPCode(secondTOTPSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -82,3 +86,16 @@ func (hs *HeartbeatService) isTimestampValid(timestamp int64) bool {
|
||||
// 允许5分钟的时间偏差
|
||||
return diff < 300 && diff > -300
|
||||
}
|
||||
|
||||
// GetAllHostInfo 获取所有主机信息
|
||||
func (hs *HeartbeatService) GetAllHostInfo() (map[string]models.HostInfo, error) {
|
||||
// 调用AuthService的方法获取所有主机信息
|
||||
hostInfoMap := hs.authService.GetAllHostInfo()
|
||||
|
||||
// 如果没有主机信息,返回一个空的map
|
||||
if len(hostInfoMap) == 0 {
|
||||
return make(map[string]models.HostInfo), nil
|
||||
}
|
||||
|
||||
return hostInfoMap, nil
|
||||
}
|
||||
|
||||
@@ -1,41 +1,31 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"cmii-uav-watchdog-common/totp_tier_one"
|
||||
"cmii-uav-watchdog/config"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
otp "cmii-uav-watchdog-otp"
|
||||
"cmii-uav-watchdog-otp/totp"
|
||||
)
|
||||
|
||||
var tierTwoTOTPSecretOpts = totp.GenerateOpts{
|
||||
SecretSize: 32,
|
||||
Issuer: "cmii-uav-watchdog",
|
||||
AccountName: "cmii-uav-watchdog",
|
||||
Period: 30,
|
||||
Secret: []byte{},
|
||||
Digits: otp.DigitsSix,
|
||||
Algorithm: otp.AlgorithmSHA1,
|
||||
Rand: nil,
|
||||
}
|
||||
|
||||
// TOTPService TOTP服务
|
||||
type TOTPService struct {
|
||||
secret string
|
||||
tierOneSecret string
|
||||
}
|
||||
|
||||
// NewTOTPService 创建TOTP服务
|
||||
func NewTOTPService() *TOTPService {
|
||||
secret := config.GetConfig().TierOneAuth.TierOneSecret
|
||||
if secret == "" {
|
||||
panic("TierOne TOTP tierOneSecret is not set ! can not start the service!")
|
||||
}
|
||||
|
||||
return &TOTPService{
|
||||
secret: config.GetConfig().Auth.Secret,
|
||||
tierOneSecret: secret,
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateTierOneTOTP 生成一级TOTP验证码
|
||||
func (ts *TOTPService) GenerateTierOneTOTP() (string, error) {
|
||||
// 使用当前时间生成TOTP
|
||||
code, err := totp.GenerateCode(ts.secret, time.Now())
|
||||
code, err := totp_tier_one.GenerateTierOneTOTPCode(ts.tierOneSecret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -46,41 +36,7 @@ func (ts *TOTPService) GenerateTierOneTOTP() (string, error) {
|
||||
// VerifyTierOneTOTP 验证一级TOTP验证码
|
||||
func (ts *TOTPService) VerifyTierOneTOTP(code string) bool {
|
||||
// 验证TOTP
|
||||
valid := totp.Validate(code, ts.secret)
|
||||
if !valid {
|
||||
return false
|
||||
}
|
||||
valid := totp_tier_one.VerifyTierOneTOTPCode(code, ts.tierOneSecret)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// GenerateTierTwoTOTPSecret 生成二级TOTP密钥
|
||||
func (ts *TOTPService) GenerateTierTwoTOTPSecret() (string, error) {
|
||||
secret, err := totp.Generate(tierTwoTOTPSecretOpts)
|
||||
if err != nil {
|
||||
log.Printf("生成TOTP密钥失败: %v", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
return secret.Secret(), nil
|
||||
}
|
||||
|
||||
// GenerateTierTwoTOTPCode 生成二级TOTP验证码
|
||||
func (ts *TOTPService) GenerateTierTwoTOTPCode(secret string) (string, error) {
|
||||
code, err := totp.GenerateCode(secret, time.Now())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// VerifyTierTwoTOTPCode 验证二级TOTP验证码
|
||||
func (ts *TOTPService) VerifyTierTwoTOTPCode(code string, secret string) bool {
|
||||
validateOpts := totp.ValidateOpts{}
|
||||
validateOpts.ConvertToValidateOpts(tierTwoTOTPSecretOpts)
|
||||
valid, err := totp.ValidateCustom(code, secret, time.Now(), validateOpts)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return valid
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user