1、google验证器

2、导出告警去重
3、去掉提示音
This commit is contained in:
2025-07-16 18:22:11 +08:00
parent 2e35d55838
commit 180e0e6957
15 changed files with 453 additions and 85 deletions

View File

@ -0,0 +1,66 @@
package helper
import (
"fmt"
"strings"
"time"
"github.com/pquerna/otp"
"github.com/pquerna/otp/totp"
)
// GoogleAuth 用于管理 TOTP 的生成和验证
type GoogleAuth struct {
Issuer string // 项目名称或公司名 WindowsLock
}
// NewGoogleAuth 创建一个 GoogleAuth 实例
func NewGoogleAuth() *GoogleAuth {
return &GoogleAuth{
Issuer: "WindowsLock",
}
}
// GenerateSecret 生成一个用户绑定谷歌验证器所需的密钥和二维码 URL
func (g *GoogleAuth) GenerateSecret(account string) (secret string, otpAuthUrl string, err error) {
key, err := totp.Generate(totp.GenerateOpts{
Issuer: g.Issuer,
AccountName: account,
Period: 30,
SecretSize: 20,
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA1,
})
if err != nil {
return "", "", err
}
return key.Secret(), key.URL(), nil
}
// VerifyCode 验证用户输入的 TOTP 验证码是否正确
func (g *GoogleAuth) VerifyCode(secret, code string) bool {
valid := totp.Validate(code, secret)
return valid
}
// VerifyCodeWithTolerance 带时间偏移容错的验证码校验容忍1个时间步长
func (g *GoogleAuth) VerifyCodeWithTolerance(secret, inputCode string) (bool, error) {
code := strings.TrimSpace(inputCode)
return totp.ValidateCustom(code, secret, time.Now(), totp.ValidateOpts{
Period: 30,
Skew: 1, // 允许前后 1 个周期±30 秒)内的验证码
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA1,
})
}
// GenerateQRCodeURL 生成 otpauth:// URL适合用在二维码中
func (g *GoogleAuth) GenerateQRCodeURL(account, secret string) string {
return fmt.Sprintf("otpauth://totp/%s:%s?secret=%s&issuer=%s", g.Issuer, account, secret, g.Issuer)
}
func (g *GoogleAuth) GenerateCode(secret string) (string, error) {
return totp.GenerateCode(secret, time.Now())
}

View File

@ -5,6 +5,8 @@ import (
"go-admin/common"
"net/http"
"go-admin/common/global"
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/sdk"
"github.com/go-admin-team/go-admin-core/sdk/api"
@ -15,14 +17,14 @@ import (
"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user"
"github.com/go-admin-team/go-admin-core/sdk/pkg/response"
"github.com/mssola/user_agent"
"go-admin/common/global"
)
func PayloadFunc(data interface{}) jwt.MapClaims {
if v, ok := data.(map[string]interface{}); ok {
u, _ := v["user"].(SysUser)
r, _ := v["role"].(SysRole)
return jwt.MapClaims{
result := jwt.MapClaims{
jwt.IdentityKey: u.UserId,
jwt.RoleIdKey: r.RoleId,
jwt.RoleKey: r.RoleKey,
@ -30,6 +32,8 @@ func PayloadFunc(data interface{}) jwt.MapClaims {
jwt.DataScopeKey: r.DataScope,
jwt.RoleNameKey: r.RoleName,
}
return result
}
return jwt.MapClaims{}
}

View File

@ -0,0 +1 @@
package handler

View File

@ -2,27 +2,29 @@ package handler
import (
"go-admin/common/models"
"gorm.io/gorm"
)
type SysUser struct {
UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"`
Username string `json:"username" gorm:"size:64;comment:用户名"`
Password string `json:"-" gorm:"size:128;comment:密码"`
NickName string `json:"nickName" gorm:"size:128;comment:昵称"`
Phone string `json:"phone" gorm:"size:11;comment:手机号"`
RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"`
Salt string `json:"-" gorm:"size:255;comment:加盐"`
Avatar string `json:"avatar" gorm:"size:255;comment:头像"`
Sex string `json:"sex" gorm:"size:255;comment:性别"`
Email string `json:"email" gorm:"size:128;comment:邮箱"`
DeptId int `json:"deptId" gorm:"size:20;comment:部门"`
PostId int `json:"postId" gorm:"size:20;comment:岗位"`
Remark string `json:"remark" gorm:"size:255;comment:备注"`
Status string `json:"status" gorm:"size:4;comment:状态"`
DeptIds []int `json:"deptIds" gorm:"-"`
PostIds []int `json:"postIds" gorm:"-"`
RoleIds []int `json:"roleIds" gorm:"-"`
UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"`
Username string `json:"username" gorm:"size:64;comment:用户名"`
Password string `json:"-" gorm:"size:128;comment:密码"`
NickName string `json:"nickName" gorm:"size:128;comment:昵称"`
Phone string `json:"phone" gorm:"size:11;comment:手机号"`
RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"`
Salt string `json:"-" gorm:"size:255;comment:加盐"`
Avatar string `json:"avatar" gorm:"size:255;comment:头像"`
Sex string `json:"sex" gorm:"size:255;comment:性别"`
Email string `json:"email" gorm:"size:128;comment:邮箱"`
DeptId int `json:"deptId" gorm:"size:20;comment:部门"`
PostId int `json:"postId" gorm:"size:20;comment:岗位"`
Remark string `json:"remark" gorm:"size:255;comment:备注"`
Status string `json:"status" gorm:"size:4;comment:状态"`
DeptIds []int `json:"deptIds" gorm:"-"`
PostIds []int `json:"postIds" gorm:"-"`
RoleIds []int `json:"roleIds" gorm:"-"`
GoogleSecret string `json:"googleSecret" gorm:"size:100;comment:谷歌验证器秘钥"`
//Dept *SysDept `json:"dept"`
models.ControlBy
models.ModelTime