diff --git a/app/admin/apis/mm_alarm_log.go b/app/admin/apis/mm_alarm_log.go index eb28704..f9ebed1 100644 --- a/app/admin/apis/mm_alarm_log.go +++ b/app/admin/apis/mm_alarm_log.go @@ -215,3 +215,21 @@ func (e MmAlarmLog) ClearAll(c *gin.Context) { e.OK(nil, "清空成功") } + +// Export 导出钱包告警记录 +func (e MmAlarmLog) Export(c *gin.Context) { + req := dto.MmAlarmLogGetPageReq{} + s := service.MmAlarmLog{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + s.Export(&req, c) +} diff --git a/app/admin/apis/sys_user.go b/app/admin/apis/sys_user.go index 645c4c8..f172b87 100644 --- a/app/admin/apis/sys_user.go +++ b/app/admin/apis/sys_user.go @@ -1,6 +1,7 @@ package apis import ( + "errors" "go-admin/app/admin/models" "net/http" @@ -456,6 +457,7 @@ func (e SysUser) GetInfo(c *gin.Context) { mp["deptId"] = sysUser.DeptId mp["name"] = sysUser.NickName mp["code"] = 200 + e.OK(mp, "") } @@ -481,3 +483,103 @@ func (e SysUser) GetList(c *gin.Context) { } e.OK(datas, "查询成功") } + +// 是否需要检查google验证器 +func (e SysUser) NeedCheckGoogleAuth(c *gin.Context) { + s := service.SysUser{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + needGoogleAuth, err := s.NeedCheckGoogleAuth(user.GetUserId(c)) + + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + e.OK(needGoogleAuth, "查询成功") +} + +// 检查谷歌验证码 +func (e SysUser) CheckGoogleAuth(c *gin.Context) { + s := service.SysUser{} + req := dto.CheckGoogleAuthReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + if req.Code == "" { + e.Error(500, errors.New("验证码不能为空"), "验证码不能为空") + return + } + + result, err := s.CheckGoogleAuth(&req, user.GetUserId(c)) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + e.OK(result, "验证成功") +} + +// 获取是否需要绑定google验证器 +func (e SysUser) NeedGooglAuth(c *gin.Context) { + s := service.SysUser{} + err := e.MakeContext(c). + MakeOrm(). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + userId := user.GetUserId(c) + + need, err := s.NeedGooglAuth(userId) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + e.OK(need, "查询成功") +} + +func (e SysUser) SetGoogleSecret(c *gin.Context) { + s := service.SysUser{} + req := dto.SetGoogleSecretReq{} + err := e.MakeContext(c). + MakeOrm(). + Bind(&req). + MakeService(&s.Service). + Errors + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + + err = s.SetGoogleSecret(&req, user.GetUserId(c)) + if err != nil { + e.Logger.Error(err) + e.Error(500, err, err.Error()) + return + } + e.OK(nil, "设置成功") +} diff --git a/app/admin/models/sys_user.go b/app/admin/models/sys_user.go index eab2cad..be4b4f0 100644 --- a/app/admin/models/sys_user.go +++ b/app/admin/models/sys_user.go @@ -2,29 +2,31 @@ package models import ( "go-admin/common/models" + "golang.org/x/crypto/bcrypt" "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:"-"` - Dept *SysDept `json:"dept"` + 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 } diff --git a/app/admin/router/mm_alarm_log.go b/app/admin/router/mm_alarm_log.go index 89b1b65..c47846a 100644 --- a/app/admin/router/mm_alarm_log.go +++ b/app/admin/router/mm_alarm_log.go @@ -25,5 +25,6 @@ func registerMmAlarmLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMid r.DELETE("", api.Delete) r.DELETE("clear-all", actions.PermissionAction(), api.ClearAll) //清理所有数据 + r.GET("export", actions.PermissionAction(), api.Export) //导出数据 } } diff --git a/app/admin/router/sys_user.go b/app/admin/router/sys_user.go index be645b4..711aa11 100644 --- a/app/admin/router/sys_user.go +++ b/app/admin/router/sys_user.go @@ -37,5 +37,10 @@ func registerSysUserRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle { v1auth.GET("/getinfo", api.GetInfo) v1auth.GET("/sys-user/options", api.GetList) + + v1auth.GET("need-check-google-auth", api.NeedCheckGoogleAuth) //是否需要检查google验证 + v1auth.GET("need-auth", api.NeedGooglAuth) //是否需要配置谷歌验证 + v1auth.PUT("set-google-auth", api.SetGoogleSecret) //设置谷歌验证 + v1auth.GET("google-code", api.CheckGoogleAuth) //验证谷歌验证码 } } diff --git a/app/admin/service/dto/mm_alarm_log.go b/app/admin/service/dto/mm_alarm_log.go index 9aa32d7..b6c88eb 100644 --- a/app/admin/service/dto/mm_alarm_log.go +++ b/app/admin/service/dto/mm_alarm_log.go @@ -1,30 +1,28 @@ package dto import ( - "go-admin/app/admin/models" "go-admin/common/dto" common "go-admin/common/models" ) type MmAlarmLogGetPageReq struct { - dto.Pagination `search:"-"` - MachineId string `form:"machineId" search:"type:exact;column:machine_id;table:mm_alarm_log" comment:"设备id"` - BiosId string `form:"biosId" search:"type:exact;column:bios_id;table:mm_alarm_log" comment:"设备码"` - MmAlarmLogOrder + dto.Pagination `search:"-"` + MachineId string `form:"machineId" search:"type:exact;column:machine_id;table:mm_alarm_log" comment:"设备id"` + BiosId string `form:"biosId" search:"type:exact;column:bios_id;table:mm_alarm_log" comment:"设备码"` + MmAlarmLogOrder } type MmAlarmLogOrder struct { - Id string `form:"idOrder" search:"type:order;column:id;table:mm_alarm_log"` - MachineId string `form:"machineIdOrder" search:"type:order;column:machine_id;table:mm_alarm_log"` - BiosId string `form:"biosIdOrder" search:"type:order;column:bios_id;table:mm_alarm_log"` - Content string `form:"contentOrder" search:"type:order;column:content;table:mm_alarm_log"` - CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:mm_alarm_log"` - UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:mm_alarm_log"` - DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:mm_alarm_log"` - CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:mm_alarm_log"` - UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:mm_alarm_log"` - + Id string `form:"idOrder" search:"type:order;column:id;table:mm_alarm_log"` + MachineId string `form:"machineIdOrder" search:"type:order;column:machine_id;table:mm_alarm_log"` + BiosId string `form:"biosIdOrder" search:"type:order;column:bios_id;table:mm_alarm_log"` + Content string `form:"contentOrder" search:"type:order;column:content;table:mm_alarm_log"` + CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:mm_alarm_log"` + UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:mm_alarm_log"` + DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:mm_alarm_log"` + CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:mm_alarm_log"` + UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:mm_alarm_log"` } func (m *MmAlarmLogGetPageReq) GetNeedSearch() interface{} { @@ -32,21 +30,21 @@ func (m *MmAlarmLogGetPageReq) GetNeedSearch() interface{} { } type MmAlarmLogInsertReq struct { - Id int `json:"-" comment:"主键id"` // 主键id - MachineId string `json:"machineId" comment:"设备id"` - BiosId string `json:"biosId" comment:"设备码"` - Content string `json:"content" comment:"内容"` - common.ControlBy + Id int `json:"-" comment:"主键id"` // 主键id + MachineId string `json:"machineId" comment:"设备id"` + BiosId string `json:"biosId" comment:"设备码"` + Content string `json:"content" comment:"内容"` + common.ControlBy } -func (s *MmAlarmLogInsertReq) Generate(model *models.MmAlarmLog) { - if s.Id == 0 { - model.Model = common.Model{ Id: s.Id } - } - model.MachineId = s.MachineId - model.BiosId = s.BiosId - model.Content = s.Content - model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 +func (s *MmAlarmLogInsertReq) Generate(model *models.MmAlarmLog) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.MachineId = s.MachineId + model.BiosId = s.BiosId + model.Content = s.Content + model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 } func (s *MmAlarmLogInsertReq) GetId() interface{} { @@ -54,21 +52,21 @@ func (s *MmAlarmLogInsertReq) GetId() interface{} { } type MmAlarmLogUpdateReq struct { - Id int `uri:"id" comment:"主键id"` // 主键id - MachineId string `json:"machineId" comment:"设备id"` - BiosId string `json:"biosId" comment:"设备码"` - Content string `json:"content" comment:"内容"` - common.ControlBy + Id int `uri:"id" comment:"主键id"` // 主键id + MachineId string `json:"machineId" comment:"设备id"` + BiosId string `json:"biosId" comment:"设备码"` + Content string `json:"content" comment:"内容"` + common.ControlBy } -func (s *MmAlarmLogUpdateReq) Generate(model *models.MmAlarmLog) { - if s.Id == 0 { - model.Model = common.Model{ Id: s.Id } - } - model.MachineId = s.MachineId - model.BiosId = s.BiosId - model.Content = s.Content - model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 +func (s *MmAlarmLogUpdateReq) Generate(model *models.MmAlarmLog) { + if s.Id == 0 { + model.Model = common.Model{Id: s.Id} + } + model.MachineId = s.MachineId + model.BiosId = s.BiosId + model.Content = s.Content + model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 } func (s *MmAlarmLogUpdateReq) GetId() interface{} { @@ -77,8 +75,9 @@ func (s *MmAlarmLogUpdateReq) GetId() interface{} { // MmAlarmLogGetReq 功能获取请求参数 type MmAlarmLogGetReq struct { - Id int `uri:"id"` + Id int `uri:"id"` } + func (s *MmAlarmLogGetReq) GetId() interface{} { return s.Id } @@ -91,3 +90,9 @@ type MmAlarmLogDeleteReq struct { func (s *MmAlarmLogDeleteReq) GetId() interface{} { return s.Ids } + +type MmAlarmLogExportResp struct { + MachineId string `json:"machineId" comment:"设备id" excel:"设备id"` + BiosId string `json:"biosId" comment:"设备码" excel:"设备码"` + Content string `json:"content" comment:"内容" excel:"内容"` +} diff --git a/app/admin/service/dto/sys_user.go b/app/admin/service/dto/sys_user.go index fa1fd20..3c69985 100644 --- a/app/admin/service/dto/sys_user.go +++ b/app/admin/service/dto/sys_user.go @@ -192,3 +192,18 @@ type SysUserOptions struct { UserId int `json:"userId"` NickName string `json:"nickName"` } + +type SetGoogleSecretReq struct { + Secret string `json:"secret" vd:"len($)>0"` + Code string `json:"code" vd:"len($)>0"` +} + +type GoogleSecretResp struct { + Secret string `json:"secret"` + OtpAuthUrl string `json:"otpAuthUrl"` + NeedGooglAuth bool `json:"needGooglAuth"` +} + +type CheckGoogleAuthReq struct { + Code string `json:"code" form:"code" vd:"len($)>0"` +} diff --git a/app/admin/service/mm_alarm_log.go b/app/admin/service/mm_alarm_log.go index 3ab89ae..dbfd207 100644 --- a/app/admin/service/mm_alarm_log.go +++ b/app/admin/service/mm_alarm_log.go @@ -3,6 +3,7 @@ package service import ( "errors" + "github.com/gin-gonic/gin" "github.com/go-admin-team/go-admin-core/sdk/service" "gorm.io/gorm" @@ -10,12 +11,45 @@ import ( "go-admin/app/admin/service/dto" "go-admin/common/actions" cDto "go-admin/common/dto" + "go-admin/common/helper" ) type MmAlarmLog struct { service.Service } +// 导出列表 +func (e MmAlarmLog) Export(req *dto.MmAlarmLogGetPageReq, c *gin.Context) error { + var datas []models.MmAlarmLog + list := make([]dto.MmAlarmLogExportResp, 0) + query := e.Orm.Model(&models.MmAlarmLog{}) + + if req.MachineId != "" { + query = query.Where("machine_id = ?", req.MachineId) + } + + err := query. + Select("machine_id, bios_id, content"). + Distinct(). + Find(&datas). + Error + + if err != nil { + e.Log.Errorf("MmAlarmLogService Export error:%s \r\n", err) + return err + } + + for _, data := range datas { + list = append(list, dto.MmAlarmLogExportResp{ + MachineId: data.MachineId, + BiosId: data.BiosId, + Content: data.Content, + }) + } + + return helper.ExportExcel(c, "钱包告警记录", list, []string{}) +} + // 清除所有记录 func (e MmAlarmLog) ClearAll(p *actions.DataPermission) error { if err := e.Orm.Exec("TRUNCATE TABLE mm_alarm_log;").Error; err != nil { diff --git a/app/admin/service/mm_risk_log.go b/app/admin/service/mm_risk_log.go index 1b5b5b5..2a9d119 100644 --- a/app/admin/service/mm_risk_log.go +++ b/app/admin/service/mm_risk_log.go @@ -148,6 +148,8 @@ func (e *MmRiskLog) Remove(d *dto.MmRiskLogDeleteReq, p *actions.DataPermission) // Save 保存MmRiskLog对象 func (e *MmRiskLog) Save(req *dto.MmRiskLogBatchReq) error { datas := make([]models.MmRiskLog, 0) + configService := SysConfig{Service: e.Service} + config, _ := configService.GetByKey("wallet_alarm") for _, item := range req.Contents { data := models.MmRiskLog{} @@ -163,11 +165,13 @@ func (e *MmRiskLog) Save(req *dto.MmRiskLogBatchReq) error { return err } - helper.SafeGo(func() { - if err := e.SendMsg(datas); err != nil { - e.Log.Errorf("发送消息失败:%s", err) - } - }) + if config.ConfigValue == "1" { + helper.SafeGo(func() { + if err := e.SendMsg(datas); err != nil { + e.Log.Errorf("发送消息失败:%s", err) + } + }) + } return nil } @@ -183,7 +187,7 @@ func (e *MmRiskLog) SendMsg(datas []models.MmRiskLog) error { alarmLogs := []models.MmAlarmLog{} for _, item := range datas { - if helper.ArrayAny(addresss, item.Content) { + if helper.ArrayAny(addresss, item.Content) || item.Type != 1 { continue } diff --git a/app/admin/service/sys_user.go b/app/admin/service/sys_user.go index 8806dbf..ef4d5f5 100644 --- a/app/admin/service/sys_user.go +++ b/app/admin/service/sys_user.go @@ -4,6 +4,7 @@ import ( "errors" "go-admin/app/admin/models" "go-admin/app/admin/service/dto" + "strings" log "github.com/go-admin-team/go-admin-core/logger" "github.com/go-admin-team/go-admin-core/sdk/pkg" @@ -12,12 +13,118 @@ import ( "go-admin/common/actions" cDto "go-admin/common/dto" + "go-admin/common/helper" ) type SysUser struct { service.Service } +// CheckGoogleAuth 检查谷歌验证器 +func (e SysUser) CheckGoogleAuth(req *dto.CheckGoogleAuthReq, i int) (bool, error) { + var sysUser models.SysUser + + if err := e.Orm.Model(sysUser).Where("user_id =?", i).First(&sysUser).Error; err != nil { + return false, errors.New("获取用户信息失败") + } + + googleAuth := helper.NewGoogleAuth() + + if resp, _ := googleAuth.VerifyCodeWithTolerance(sysUser.GoogleSecret, req.Code); !resp { + return false, errors.New("验证码错误") + } + + return true, nil +} + +// 是否需要检查google验证器 +func (e SysUser) NeedCheckGoogleAuth(i int) (bool, error) { + var sysUser models.SysUser + + if err := e.Orm.Model(sysUser).Where("user_id =?", i).First(&sysUser).Error; err != nil { + e.Log.Errorf("获取用户信息失败 %v", err) + return false, errors.New("获取用户信息失败") + } + + configService := SysConfig{} + configService.Orm = e.Orm + configService.Log = e.Log + + configData, _ := configService.GetByKey("google_auth") + needGooleAuth := false + + if configData.ConfigValue == "1" && sysUser.GoogleSecret != "" { + needGooleAuth = true + } + + return needGooleAuth, nil +} + +func (e SysUser) SetGoogleSecret(req *dto.SetGoogleSecretReq, i int) error { + var user models.SysUser + + if err := e.Orm.Model(user).Where("user_id =?", i).First(&user).Error; err != nil { + e.Log.Errorf("db error: %v", err) + return errors.New("获取用户信息失败") + } + + if user.GoogleSecret != "" { + return errors.New("该用户已绑定谷歌验证器") + } + + googleAuth := helper.NewGoogleAuth() + + if !googleAuth.VerifyCode(req.Secret, req.Code) { + return errors.New("验证码错误") + } + + db := e.Orm.Model(&models.SysUser{}).Where("user_id =?", i).Update("google_secret", req.Secret) + + if db.Error != nil { + e.Log.Errorf("db error: %s", db.Error) + return db.Error + } + + if db.RowsAffected == 0 { + return errors.New("绑定goole验证器失败") + } + + return nil +} + +func (e SysUser) NeedGooglAuth(userId int) (dto.GoogleSecretResp, error) { + var sysUser models.SysUser + configService := SysConfig{} + configService.Orm = e.Orm + configService.Log = e.Log + googleAuthConfig, _ := configService.GetByKey("google_auth") + result := dto.GoogleSecretResp{ + NeedGooglAuth: false, + } + + err := e.Orm.Model(&models.SysUser{}).Where("user_id =?", userId).Select("user_id, google_secret,username").First(&sysUser).Error + if err != nil { + e.Log.Errorf("db error: %s", err) + return result, errors.New("获取用户信息失败") + } + + if strings.Trim(googleAuthConfig.ConfigValue, " ") == "1" && sysUser.GoogleSecret == "" { + result.NeedGooglAuth = true + googleAuth := helper.NewGoogleAuth() + secret, otpAuthUrl, err := googleAuth.GenerateSecret(sysUser.Username) + + if err != nil { + e.Log.Errorf("生成谷歌验证器失败: %s", err) + return result, errors.New("生成谷歌验证器失败") + } + + result.Secret = secret + result.OtpAuthUrl = otpAuthUrl + } + + return result, nil +} + // 根据权限获取user id func (e SysUser) GetByPermission(permission string) ([]int, error) { result := make([]int, 0) diff --git a/common/helper/google_auth.go b/common/helper/google_auth.go new file mode 100644 index 0000000..c134d86 --- /dev/null +++ b/common/helper/google_auth.go @@ -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()) +} diff --git a/common/middleware/handler/auth.go b/common/middleware/handler/auth.go index ddb6791..5397147 100644 --- a/common/middleware/handler/auth.go +++ b/common/middleware/handler/auth.go @@ -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{} } diff --git a/common/middleware/handler/google_auth.go b/common/middleware/handler/google_auth.go new file mode 100644 index 0000000..b9cae43 --- /dev/null +++ b/common/middleware/handler/google_auth.go @@ -0,0 +1 @@ +package handler diff --git a/common/middleware/handler/user.go b/common/middleware/handler/user.go index b34d4db..6e1cb76 100644 --- a/common/middleware/handler/user.go +++ b/common/middleware/handler/user.go @@ -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 diff --git a/go.mod b/go.mod index 4cace6f..e661a76 100644 --- a/go.mod +++ b/go.mod @@ -48,6 +48,7 @@ require ( github.com/andeya/goutil v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmatcuk/doublestar/v4 v4.8.1 // indirect + github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect github.com/bytedance/sonic v1.13.2 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/casbin/gorm-adapter/v3 v3.32.0 // indirect @@ -110,6 +111,7 @@ require ( github.com/nyaruka/phonenumbers v1.0.55 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/pquerna/otp v1.5.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect