From 80a581486c5350e75ee366864c95a626479be8cb Mon Sep 17 00:00:00 2001 From: sunxiaolong Date: Mon, 20 Nov 2023 15:47:51 +0800 Subject: [PATCH] =?UTF-8?q?:coding:=E5=AE=8C=E6=88=90totp=E9=80=82?= =?UTF-8?q?=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.go | 8 ++ controllers/addController.go | 11 +- controllers/getController.go | 3 +- controllers/loginController.go | 19 ++- controllers/totpController.go | 121 +++++++++++++++++ controllers/updateController.go | 40 +++++- datas/datas.go | 5 + go.mod | 2 + go.sum | 4 + models/user/user_info.go | 17 ++- routers/router.go | 3 + service/deleteService.go | 1 - service/updateService.go | 3 +- utils/AES_ECB.go | 13 +- utils/date_time.go | 3 +- utils/gojson.go | 14 +- utils/mfa/mfa.go | 40 ++++++ utils/ntp/ntp.go | 71 ++++++++++ views/index.html | 88 ++++++++++++- views/login.html | 200 ++++++++++++++-------------- views/order_info.html | 222 ++++++++++++++++---------------- 21 files changed, 641 insertions(+), 247 deletions(-) create mode 100644 config/config.go create mode 100644 controllers/totpController.go create mode 100644 utils/mfa/mfa.go create mode 100644 utils/ntp/ntp.go diff --git a/config/config.go b/config/config.go new file mode 100644 index 0000000..55c0506 --- /dev/null +++ b/config/config.go @@ -0,0 +1,8 @@ +package config + +import "github.com/beego/beego/v2/server/web" + +func GetGatewayHost() string { + host, _ := web.AppConfig.String("gateway::host") + return host +} diff --git a/controllers/addController.go b/controllers/addController.go index 04fb8ee..7345542 100644 --- a/controllers/addController.go +++ b/controllers/addController.go @@ -1,3 +1,5 @@ +package controllers + /*************************************************** ** @Desc : c file for ... ** @Time : 2019/8/19 18:13 @@ -7,7 +9,6 @@ ** @Last Modified time: 2019/8/19 18:13 ** @Software: GoLand ****************************************************/ -package controllers import ( "boss/common" @@ -29,9 +30,7 @@ type AddController struct { BaseController } -/* -* 添加一级菜单 - */ +// AddMenu 添加一级菜单 func (c *AddController) AddMenu() { oneMenu := c.GetString("oneMenu") userID := c.GetSession("userID").(string) @@ -40,9 +39,7 @@ func (c *AddController) AddMenu() { c.GenerateJSON(dataJSON) } -/* -* 添加二级菜单 - */ +// AddSecondMenu 添加二级菜单 func (c *AddController) AddSecondMenu() { firstMenuUid := c.GetString("preMenuUid") secondMenu := c.GetString("secondMenu") diff --git a/controllers/getController.go b/controllers/getController.go index 7858ec6..2237355 100644 --- a/controllers/getController.go +++ b/controllers/getController.go @@ -1,3 +1,5 @@ +package controllers + /*************************************************** ** @Desc : c file for ... ** @Time : 2019/8/21 11:18 @@ -7,7 +9,6 @@ ** @Last Modified time: 2019/8/21 11:18 ** @Software: GoLand ****************************************************/ -package controllers import ( "boss/common" diff --git a/controllers/loginController.go b/controllers/loginController.go index 8c13a32..dc40cde 100644 --- a/controllers/loginController.go +++ b/controllers/loginController.go @@ -5,6 +5,7 @@ import ( "boss/datas" "boss/models/user" "boss/utils" + "boss/utils/mfa" "github.com/beego/beego/v2/adapter/validation" "github.com/beego/beego/v2/core/logs" beego "github.com/beego/beego/v2/server/web" @@ -15,7 +16,6 @@ type LoginController struct { } func (c *LoginController) Prepare() { - } func (c *LoginController) Login() { @@ -23,6 +23,7 @@ func (c *LoginController) Login() { userID := c.GetString("userID") passWD := c.GetString("passwd") code := c.GetString("Code") + totpCode := c.GetString("totpCode") dataJSON := new(datas.KeyDataJSON) @@ -44,7 +45,19 @@ func (c *LoginController) Login() { if userInfo.UserId == "" { dataJSON.Key = "userID" dataJSON.Msg = "用户不存在,请求联系管理员!" + } else if userInfo.OtpSecret != "" && totpCode == "" { + dataJSON.Key = "userID" + dataJSON.Msg = "需要输入二次验证!" } else { + // 如果验证失败 + if userInfo.OtpSecret != "" && !mfa.ValidCode(totpCode, userInfo.OtpSecret) { + dataJSON.Key = "userID" + dataJSON.Msg = "二次验证不正确,请输入二次验证!" + c.Data["json"] = dataJSON + _ = c.ServeJSON() + return + } + codeInterface := c.GetSession("verifyCode") if userInfo.Passwd != utils.GetMD5Upper(passWD) { dataJSON.Key = "passWD" @@ -92,9 +105,7 @@ func (c *LoginController) Logout() { _ = c.ServeJSON() } -/* -* 验证码获取,如果获取成功,并将验证码存到session中 - */ +// GetVerifyImg 验证码获取,如果获取成功,并将验证码存到session中 func (c *LoginController) GetVerifyImg() { Image, verifyCode := utils.GenerateVerifyCodeImg() if Image == nil || len(verifyCode) != common.VERIFY_CODE_LEN { diff --git a/controllers/totpController.go b/controllers/totpController.go new file mode 100644 index 0000000..18ce8e9 --- /dev/null +++ b/controllers/totpController.go @@ -0,0 +1,121 @@ +package controllers + +import ( + "boss/datas" + "boss/models/user" + "boss/utils/mfa" + "github.com/beego/beego/v2/server/web" +) + +type TotpQuery struct { + web.Controller +} + +func (c *TotpQuery) GenTotp() { + userID, ok := c.GetSession("userID").(string) + if !ok { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "提交信息错误", + } + _ = c.ServeJSON() + return + + } + + userInfo := user.GetUserInfoByUserID(userID) + if userInfo.UserId == "" { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "当前用户不存在", + } + _ = c.ServeJSON() + return + } + + otp, err := mfa.GetOtp(userInfo.UserId, userInfo.Nick) + if err != nil { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "当前用户不存在", + } + _ = c.ServeJSON() + return + + } + + c.Data["json"] = datas.KeyDataJSON2{ + KeyDataJSON: datas.KeyDataJSON{ + Code: 0, + Msg: "成功", + Key: "", + }, + Data: otp, + } + _ = c.ServeJSON() +} + +func (c *TotpQuery) SaveTotp() { + code := c.GetString("code") + secret := c.GetString("secret") + + if code == "" || secret == "" { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "提交消息不准确", + } + _ = c.ServeJSON() + return + } + + userID, ok := c.GetSession("userID").(string) + if !ok { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "提交信息错误", + } + _ = c.ServeJSON() + return + + } + + userInfo := user.GetUserInfoByUserID(userID) + if userInfo.UserId == "" { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "当前用户不存在", + } + _ = c.ServeJSON() + return + + } + + ok = mfa.ValidCode(code, secret) + + if !ok { + c.Data["json"] = datas.KeyDataJSON{ + Code: -1, + Msg: "code验证错误", + } + _ = c.ServeJSON() + return + + } + + err2 := user.UpdateOtpByUserID(userInfo.UserId, secret) + if err2 != nil { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "更新totp失败", + } + _ = c.ServeJSON() + return + + } + + c.Data["json"] = datas.KeyDataJSON{ + Code: 0, + Msg: "success", + } + _ = c.ServeJSON() +} diff --git a/controllers/updateController.go b/controllers/updateController.go index 54044f4..b4383b9 100644 --- a/controllers/updateController.go +++ b/controllers/updateController.go @@ -14,6 +14,7 @@ import ( "boss/models/user" "boss/service" "boss/utils" + "boss/utils/mfa" "github.com/beego/beego/v2/core/validation" "strings" ) @@ -197,9 +198,7 @@ func (c *UpdateController) ResetAgentPassword() { c.GenerateJSON(se.ResetAgentPassword(agentUid, newPassword, newVertifyPassword)) } -/* -* 手动选择了打款通道 - */ +// ChoosePayForRoad 手动选择了打款通道 func (c *UpdateController) ChoosePayForRoad() { roadName := strings.TrimSpace(c.GetString("roadName")) bankOrderId := strings.TrimSpace(c.GetString("bankOrderId")) @@ -211,9 +210,7 @@ func (c *UpdateController) ChoosePayForRoad() { c.GenerateJSON(se.ChoosePayForRoad(confirmType, roadName, bankOrderId, remark)) } -/* -* 处理打款结果的处理 - */ +// ResultPayFor 处理打款结果的处理 func (c *UpdateController) ResultPayFor() { resultType := strings.TrimSpace(c.GetString("resultType")) bankOrderId := strings.TrimSpace(c.GetString("bankOrderId")) @@ -227,6 +224,37 @@ func (c *UpdateController) UpdateOrderStatus() { bankOrderId := strings.TrimSpace(c.GetString("bankOrderId")) solveType := strings.TrimSpace(c.GetString("solveType")) operator := strings.TrimSpace(c.GetString("operator")) + code := strings.TrimSpace(c.GetString("totpCode")) + + userID, ok := c.GetSession("userID").(string) + if !ok { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "提交信息错误", + } + _ = c.ServeJSON() + return + + } + + userInfo := user.GetUserInfoByUserID(userID) + if userInfo.UserId == "" { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "当前用户不存在", + } + _ = c.ServeJSON() + return + } + + if !mfa.ValidCode(code, userInfo.OtpSecret) { + c.Data["json"] = datas.BaseDataJSON{ + Code: -1, + Msg: "二次验证失败", + } + _ = c.ServeJSON() + return + } se := new(service.UpdateService) diff --git a/datas/datas.go b/datas/datas.go index 6c82d8d..b31b32a 100644 --- a/datas/datas.go +++ b/datas/datas.go @@ -22,6 +22,11 @@ type KeyDataJSON struct { Key string } +type KeyDataJSON2 struct { + KeyDataJSON + Data interface{} +} + type MenuDataJSON struct { StartIndex int DisplayCount int diff --git a/go.mod b/go.mod index a708b12..3f742bd 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,6 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/rs/xid v1.2.1 + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect + github.com/xlzd/gotp v0.1.0 // indirect ) diff --git a/go.sum b/go.sum index ba6a8fc..606f1ca 100644 --- a/go.sum +++ b/go.sum @@ -316,6 +316,8 @@ github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -340,6 +342,8 @@ github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnD github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlzd/gotp v0.1.0 h1:37blvlKCh38s+fkem+fFh7sMnceltoIEBYTVXyoa5Po= +github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8qg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= diff --git a/models/user/user_info.go b/models/user/user_info.go index 70d3f2c..2124dc4 100644 --- a/models/user/user_info.go +++ b/models/user/user_info.go @@ -1,3 +1,5 @@ +package user + /*************************************************** ** @Desc : This file for ... ** @Time : 2019/8/9 14:02 @@ -7,7 +9,6 @@ ** @Last Modified time: 2019/8/9 14:02 ** @Software: GoLand ****************************************************/ -package user import ( "github.com/beego/beego/v2/client/orm" @@ -30,6 +31,7 @@ type UserInfo struct { RoleName string CreateTime string UpdateTime string + OtpSecret string } func GetUserInfoByUserID(userID string) UserInfo { @@ -42,6 +44,19 @@ func GetUserInfoByUserID(userID string) UserInfo { return userInfo } +func UpdateOtpByUserID(userID, totpSecret string) error { + o := orm.NewOrm() + _, err := o.QueryTable(USERINFO).Exclude("status", "delete"). + Filter("user_id", userID). + Update(orm.Params{"otp_secret": totpSecret}) + + if err != nil { + logs.Error("更新totp失败", err) + } + + return err +} + func GetOperatorByMap(params map[string]string, displayCount, offset int) []UserInfo { o := orm.NewOrm() var userInfo []UserInfo diff --git a/routers/router.go b/routers/router.go index d8cba2c..a81257f 100644 --- a/routers/router.go +++ b/routers/router.go @@ -107,4 +107,7 @@ func init() { web.Router("/result/payfor", &controllers.UpdateController{}, "*:ResultPayFor") web.Router("/send/notify", &controllers.SendNotify{}, "*:SendNotifyToMerchant") web.Router("/self/send/notify", &controllers.SendNotify{}, "*:SelfSendNotify") + + web.Router("/user/genTotp", &controllers.TotpQuery{}, "*:GenTotp") + web.Router("/user/saveTotp", &controllers.TotpQuery{}, "*:SaveTotp") } diff --git a/service/deleteService.go b/service/deleteService.go index 94e9ff9..31e2e86 100644 --- a/service/deleteService.go +++ b/service/deleteService.go @@ -206,7 +206,6 @@ func (c *DeleteService) DeleteMerchant(merchantUid string) *datas.KeyDataJSON { func (c *DeleteService) DeleteAccount(accountUid string) *datas.BaseDataJSON { dataJSON := new(datas.BaseDataJSON) - merchant.IsExistByMerchantUid(accountUid) if merchant.IsExistByMerchantUid(accountUid) || agent.IsExistByAgentUid(accountUid) { dataJSON.Code = -1 dataJSON.Msg = "用户还存在,不能删除" diff --git a/service/updateService.go b/service/updateService.go index 9e0db16..9d37482 100644 --- a/service/updateService.go +++ b/service/updateService.go @@ -2,6 +2,7 @@ package service import ( "boss/common" + "boss/config" "boss/datas" "boss/models" "boss/models/accounts" @@ -376,7 +377,7 @@ func (c *UpdateService) ChoosePayForRoad(confirmType, roadName, bankOrderId, rem func (c *UpdateService) UpdateOrderStatus(bankOrderId, solveType, operator string) *datas.KeyDataJSON { keyDataJSON := new(datas.KeyDataJSON) - updateOrderUrl, _ := web.AppConfig.String("gateway::host") + updateOrderUrl := config.GetGatewayHost() res, err := httplib.Get(updateOrderUrl + "gateway/update/order" + "?bankOrderId=" + bankOrderId + "&solveType=" + solveType + "&operator=" + operator).String() if err != nil { diff --git a/utils/AES_ECB.go b/utils/AES_ECB.go index 76d6eeb..2f63df9 100644 --- a/utils/AES_ECB.go +++ b/utils/AES_ECB.go @@ -1,3 +1,5 @@ +package utils + /*************************************************** ** @Desc : This file for ... ** @Time : 2018-8-30 13:50 @@ -7,7 +9,6 @@ ** @Last Modified time: 2018-8-30 13:50 ** @Software: GoLand ****************************************************/ -package utils import ( "bytes" @@ -17,12 +18,10 @@ import ( "github.com/beego/beego/v2/core/logs" ) -/* -aes解码 -crypted:要加密的字符串 -key:用来加密的密钥 密钥长度可以是128bit、192bit、256bit中的任意一个 -16位key对应128bit -*/ +// AesDecrypt aes解码 +// crypted:要加密的字符串 +// key:用来加密的密钥 密钥长度可以是128bit、192bit、256bit中的任意一个 +// 16位key对应128bit func AesDecrypt(src, key []byte) []byte { block, err := aes.NewCipher(key) if err != nil { diff --git a/utils/date_time.go b/utils/date_time.go index 919b998..c047827 100644 --- a/utils/date_time.go +++ b/utils/date_time.go @@ -1,3 +1,5 @@ +package utils + /*************************************************** ** @Desc : This file for ... ** @Time : 2019/8/21 10:21 @@ -7,7 +9,6 @@ ** @Last Modified time: 2019/8/21 10:21 ** @Software: GoLand ****************************************************/ -package utils import "time" diff --git a/utils/gojson.go b/utils/gojson.go index e0d75bc..1c36cf9 100644 --- a/utils/gojson.go +++ b/utils/gojson.go @@ -12,7 +12,7 @@ type Js struct { data interface{} } -// Initialize the json configruation +// Json Initialize the json configruation func Json(data string) *Js { j := new(Js) var f interface{} @@ -24,7 +24,7 @@ func Json(data string) *Js { return j } -// According to the key of the returned data information,return js.data +// Get According to the key of the returned data information,return js.data func (j *Js) Get(key string) *Js { m := j.Getdata() if v, ok := m[key]; ok { @@ -35,7 +35,7 @@ func (j *Js) Get(key string) *Js { return j } -// 判断是否有郊 +// IsValid 判断是否有郊 func (j *Js) IsValid() bool { if nil == j.data { return false @@ -44,7 +44,7 @@ func (j *Js) IsValid() bool { } } -// return json data +// Getdata return json data func (j *Js) Getdata() map[string]interface{} { if m, ok := (j.data).(map[string]interface{}); ok { return m @@ -94,7 +94,7 @@ func (j *Js) Getindex(i int) *Js { return j } -// When the data {"result":["username","password"]} can use arrayindex(1) get the username +// Arrayindex When the data {"result":["username","password"]} can use arrayindex(1) get the username func (j *Js) Arrayindex(i int) string { num := i - 1 if i > len((j.data).([]interface{})) { @@ -121,7 +121,7 @@ func (j *Js) Arrayindex(i int) string { } -// The data must be []interface{} ,According to your custom number to return your key and array data +// Getkey The data must be []interface{} ,According to your custom number to return your key and array data func (j *Js) Getkey(key string, i int) *Js { num := i - 1 if i > len((j.data).([]interface{})) { @@ -140,7 +140,7 @@ func (j *Js) Getkey(key string, i int) *Js { return j } -// According to the custom of the PATH to find the PATH +// Getpath According to the custom of the PATH to find the PATH func (j *Js) Getpath(args ...string) *Js { d := j for i := range args { diff --git a/utils/mfa/mfa.go b/utils/mfa/mfa.go new file mode 100644 index 0000000..4c50718 --- /dev/null +++ b/utils/mfa/mfa.go @@ -0,0 +1,40 @@ +package mfa + +import ( + "bytes" + "encoding/base64" + "strconv" + "time" + + "github.com/skip2/go-qrcode" + "github.com/xlzd/gotp" +) + +const secretLength = 16 + +type Otp struct { + Secret string `json:"secret"` + QrImage string `json:"qrImage"` +} + +func GetOtp(userId, username string) (otp Otp, err error) { + secret := gotp.RandomSecret(secretLength) + otp.Secret = secret + totp := gotp.NewDefaultTOTP(secret) + uri := totp.ProvisioningUri(userId, "kami "+username) + subImg, err := qrcode.Encode(uri, qrcode.Medium, 256) + dist := make([]byte, 3000) + base64.StdEncoding.Encode(dist, subImg) + index := bytes.IndexByte(dist, 0) + baseImage := dist[0:index] + otp.QrImage = "data:image/png;base64," + string(baseImage) + return +} + +func ValidCode(code string, secret string) bool { + totp := gotp.NewDefaultTOTP(secret) + now := time.Now().Unix() + strInt64 := strconv.FormatInt(now, 10) + id16, _ := strconv.Atoi(strInt64) + return totp.Verify(code, int64(id16)) +} diff --git a/utils/ntp/ntp.go b/utils/ntp/ntp.go new file mode 100644 index 0000000..7259030 --- /dev/null +++ b/utils/ntp/ntp.go @@ -0,0 +1,71 @@ +package ntp + +import ( + "encoding/binary" + "fmt" + "net" + "runtime" + "time" + + "github.com/gogf/gf/os/gproc" +) + +const ntpEpochOffset = 2208988800 + +type packet struct { + Settings uint8 + Stratum uint8 + Poll int8 + Precision int8 + RootDelay uint32 + RootDispersion uint32 + ReferenceID uint32 + RefTimeSec uint32 + RefTimeFrac uint32 + OrigTimeSec uint32 + OrigTimeFrac uint32 + RxTimeSec uint32 + RxTimeFrac uint32 + TxTimeSec uint32 + TxTimeFrac uint32 +} + +func Getremotetime() (time.Time, error) { + conn, err := net.Dial("udp", "pool.ntp.org:123") + if err != nil { + return time.Time{}, fmt.Errorf("failed to connect: %v", err) + } + defer conn.Close() + if err := conn.SetDeadline(time.Now().Add(15 * time.Second)); err != nil { + return time.Time{}, fmt.Errorf("failed to set deadline: %v", err) + } + + req := &packet{Settings: 0x1B} + + if err := binary.Write(conn, binary.BigEndian, req); err != nil { + return time.Time{}, fmt.Errorf("failed to set request: %v", err) + } + + rsp := &packet{} + if err := binary.Read(conn, binary.BigEndian, rsp); err != nil { + return time.Time{}, fmt.Errorf("failed to read server response: %v", err) + } + + secs := float64(rsp.TxTimeSec) - ntpEpochOffset + nanos := (int64(rsp.TxTimeFrac) * 1e9) >> 32 + + showtime := time.Unix(int64(secs), nanos) + + return showtime, nil +} + +func UpdateSystemDate(dateTime string) error { + system := runtime.GOOS + if system == "linux" { + if _, err := gproc.ShellExec(`date -s "` + dateTime + `"`); err != nil { + return fmt.Errorf("update system date failed, err: %v", err) + } + return nil + } + return fmt.Errorf("The current system architecture does not support synchronization") +} diff --git a/views/index.html b/views/index.html index d7f6138..3df930d 100644 --- a/views/index.html +++ b/views/index.html @@ -161,7 +161,6 @@ *
-
@@ -184,6 +183,41 @@
+ + +
@@ -205,7 +239,10 @@ 更改密码 - +
  • + 二次验证 +
  • { + if (res.Code === 0) { + $("#totp-img img").attr("src", res.Data.qrImage); + $("#totp-secret").attr("value", res.Data.secret); + } else { + alert(res.Msg) + } + }, + }) + }); + $(".totp-save").click(function (event) { + // 获取secret + const secret = $("#totp-secret").val(); + const code = $("#totp-value").val(); + if (secret === "" || code === "") { + setError(".totp-new-error", "信息填写不完整,需要重新填写"); + return; + } + + $.ajax({ + url: "/user/saveTotp", + method: "post", + data: { + code: code, + secret: secret, + }, + success: (res) => { + if (res.Code === 0) { + $("#totp-secret").val(""); + $("#totp-value").val(""); + $(".cancal-save").trigger('click'); + alert("保存成功!") + } else { + setError(".totp-new-error", res.Msg); + } + }, + error: (err) => { + setError(".totp-new-error", err); + } + }) + }) \ No newline at end of file diff --git a/views/login.html b/views/login.html index 7b87b5e..da18fa5 100644 --- a/views/login.html +++ b/views/login.html @@ -1,7 +1,10 @@ - - - + + + @@ -13,110 +16,117 @@ - + -
    -
  • + + \ No newline at end of file