package handler import ( "Medical_OAuth/app/admin/model" "Medical_OAuth/common" "Medical_OAuth/common/global" "errors" "fmt" "github.com/gin-gonic/gin" "github.com/go-redis/redis/v7" "github.com/mssola/user_agent" "gogs.baozhida.cn/zoie/OAuth-core/api" "gogs.baozhida.cn/zoie/OAuth-core/pkg" jwt "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth" "gogs.baozhida.cn/zoie/OAuth-core/pkg/jwtauth/user" "gogs.baozhida.cn/zoie/OAuth-core/pkg/response" "gogs.baozhida.cn/zoie/OAuth-core/pkg/utils" "gogs.baozhida.cn/zoie/OAuth-core/sdk" "gogs.baozhida.cn/zoie/OAuth-core/sdk/config" "gorm.io/gorm" "net/http" "strings" ) func PayloadFunc(data interface{}) jwt.MapClaims { if v, ok := data.(map[string]interface{}); ok { u, _ := v["user"].(SysUser) r, _ := v["role"].(SysRole) d, _ := v["dept"].(SysDept) single, _ := v["single"].(bool) return jwt.MapClaims{ jwt.UUIDKey: u.Uuid, jwt.IdentityKey: u.Id, jwt.RoleIdKey: r.Id, jwt.RoleKey: r.RoleKey, jwt.UserNameKey: u.Username, jwt.DataScopeKey: r.DataScope, jwt.RoleNameKey: r.Name, jwt.SingleKey: single, jwt.DeptIdKey: u.DeptId, jwt.DeptNameKey: d.DeptName, jwt.RandomKey: utils.GetRandString(8, "", 0), } } return jwt.MapClaims{} } func IdentityHandler(c *gin.Context) interface{} { claims := jwt.ExtractClaims(c) return map[string]interface{}{ "UUIDKey": claims["uuid"], "IdentityKey": claims["identity"], "UserName": claims["username"], "RoleName": claims["roleName"], "RoleKey": claims["roleKey"], "Id": claims["identity"], "RoleId": claims["roleId"], "DataScope": claims["dataScope"], "single": claims["single"], "DeptId": claims["deptId"], "DeptName": claims["deptName"], "RandomKey": claims["randomKey"], } } // Authenticator 登录认证 // Update 登录认证 // @Summary 登录认证 // @Description 登录认证 // @Tags 登录 // @Accept application/json // @Product application/json // @Param data body Login true "body" // @Success 200 {object} response.Response "{"code": 200, "data": [...]}" // @Router /api/login [post] func Authenticator(c *gin.Context) (interface{}, error) { log := api.GetRequestLogger(c) ormDB, err := pkg.GetOrm(c) if err != nil { log.Errorf("get db error, %s", err.Error()) response.Error(c, 500, err, "数据库连接获取失败") return nil, jwt.ErrFailedAuthentication } var loginVals Login var status = "2" var msg = "登录成功" var username = "" defer func() { LoginLogToDB(c, status, msg, username) }() if err = c.ShouldBind(&loginVals); err != nil { username = loginVals.Username msg = "数据解析失败" status = "1" return nil, jwt.ErrFailedAuthentication } //if config.ApplicationConfig.Mode != "dev" { // if !captcha.Verify(loginVals.UUID, loginVals.Code, true) { // username = loginVals.Username // msg = "验证码错误" // status = "1" // // return nil, jwt.ErrInvalidVerificationCode // } //} u, role, dept, e := loginVals.GetUser(ormDB) username = loginVals.Username if e != nil { msg = e.Error() status = "1" log.Warnf("%s login failed!", username) return nil, jwt.ErrFailedAuthentication } single, err := GetSingleLogin(c) if err != nil { return nil, err } return map[string]interface{}{"user": u, "role": role, "dept": dept, "single": single}, nil } // LoginLogToDB Write log to database func LoginLogToDB(c *gin.Context, status string, msg string, username string) { if !config.LoggerConfig.EnabledDB { return } log := api.GetRequestLogger(c) l := make(map[string]interface{}) ua := user_agent.New(c.Request.UserAgent()) l["ipaddr"] = common.GetClientIP(c) l["loginTime"] = pkg.GetCurrentTime() l["status"] = status l["remark"] = c.Request.UserAgent() browserName, browserVersion := ua.Browser() l["browser"] = browserName + " " + browserVersion l["os"] = ua.OS() l["platform"] = ua.Platform() l["username"] = username l["msg"] = msg q := sdk.Runtime.GetMemoryQueue(c.Request.Host) message, err := sdk.Runtime.GetStreamMessage("", global.LoginLog, l) if err != nil { log.Errorf("GetStreamMessage error, %s", err.Error()) //日志报错错误,不中断请求 } else { err = q.Append(message) if err != nil { log.Errorf("Append message error, %s", err.Error()) } } } // LogOut 退出登录 // @Summary 退出登录 // @Description 退出登录 // @Description LoginHandler can be used by clients to get a jwt token. // @Description Reply will be of the form {"token": "TOKEN"}. // @Tags 登录 // @Accept application/json // @Product application/json // @Success 200 {string} string "{"code": 200, "msg": "成功退出系统"}" // @Router /logout [post] // @Security Bearer func LogOut(c *gin.Context) { LoginLogToDB(c, "2", "退出成功", user.GetUserName(c)) c.JSON(http.StatusOK, gin.H{ "code": 200, "msg": "退出成功", }) } func Authorizator(data interface{}, c *gin.Context) bool { if v, ok := data.(map[string]interface{}); ok { u, _ := v["user"].(model.SysUser) r, _ := v["role"].(model.SysRole) d, _ := v["dept"].(model.SysDept) single, _ := v["single"].(bool) c.Set("uuid", u.Uuid) c.Set("identity", u.Id) c.Set("userName", u.Username) c.Set("roleName", r.Name) c.Set("roleKey", r.RoleKey) c.Set("userId", u.Id) c.Set("roleId", r.Id) c.Set("single", single) c.Set("dataScope", r.DataScope) c.Set("deptId", u.DeptId) c.Set("deptName", d.DeptName) c.Set("randomKey", utils.GetRandString(8, "", 0)) return true } return false } func Unauthorized(c *gin.Context, code int, message string) { c.JSON(http.StatusOK, gin.H{ "code": code, "msg": message, }) } // 保存token到redis func SaveNewestToken(c *gin.Context, userId int64, token string, expire int64) error { key := fmt.Sprintf("%s:%d", "bzd.oauth.token", userId) return sdk.Runtime.GetCacheAdapter().Set(key, token, int(expire)) } // redis从redis获取token func GetNewestToken(c *gin.Context, userId int64) (string, error) { key := fmt.Sprintf("%s:%d", "bzd.oauth.token", userId) return sdk.Runtime.GetCacheAdapter().Get(key) } func GetSingleLogin(c *gin.Context) (bool, error) { log := api.GetRequestLogger(c) ormDB, err := pkg.GetOrm(c) if err != nil { log.Errorf("get db error, %s", err.Error()) response.Error(c, 500, err, "数据库连接获取失败") return false, err } //result := map[string]interface{}{} var result string err = ormDB.Table("sys_config").Select("config_value").Where("config_key = ? ", "sys_single_login").Scan(&result).Error if err != nil { log.Errorf("get sys_config error, %s", err.Error()) if errors.Is(err, gorm.ErrRecordNotFound) { // 默认为非单一登录 return false, nil } return false, err } if result == "是" { return true, nil } return false, nil } func SetEnterDeptId(c *gin.Context, newToken string, userId int64) error { oldToken := "" list := strings.Split(c.Request.Header.Get("Authorization"), ".") if len(list) > 0 { oldToken = list[len(list)-1] } list2 := strings.Split(newToken, ".") newToken2 := list2[len(list2)-1] deptIdStr, err := sdk.Runtime.GetCacheAdapter().Get(fmt.Sprintf("enter-dept-%s-%d", oldToken, userId)) if err == nil { sdk.Runtime.GetCacheAdapter().Set(fmt.Sprintf("enter-dept-%s-%d", newToken2, userId), deptIdStr, int(config.JwtConfig.Timeout)) sdk.Runtime.GetCacheAdapter().Del(fmt.Sprintf("enter-dept-%s-%d", oldToken, userId)) } deptName, err := sdk.Runtime.GetCacheAdapter().Get(fmt.Sprintf("enter-dept-name-%s-%d", oldToken, userId)) if err == nil { sdk.Runtime.GetCacheAdapter().Set(fmt.Sprintf("enter-dept-name-%s-%d", newToken2, userId), deptName, int(config.JwtConfig.Timeout)) sdk.Runtime.GetCacheAdapter().Del(fmt.Sprintf("enter-dept-name-%s-%d", oldToken, userId)) } if err == redis.Nil { return nil } return err }