Commit 6f69d2b4 authored by 黄智's avatar 黄智

用户账户审计

parent 4d9c2fca
...@@ -5,29 +5,38 @@ import ( ...@@ -5,29 +5,38 @@ import (
) )
type SystemUser struct { type SystemUser struct {
Id int `json:"id" xorm:"pk autoincr" ` // id Id int `json:"id" xorm:"pk autoincr" ` // id
Name string `json:"name" ` // 名称 Name string `json:"name" ` // 名称
SystemAccount string `json:"system_account" ` // 账号 SystemAccount string `json:"system_account" ` // 账号
OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织 OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织
Password string `json:"password"` // 密码 Password string `json:"password"` // 密码
State int `json:"state" xorm:"state"` // 状态0禁用1启用 State int `json:"state" xorm:"state"` // 状态0禁用1启用
Logo string `json:"logo" xorm:"logo"` // 头像logo Logo string `json:"logo" xorm:"logo"` // 头像logo
CreatedBy int `json:"created_by" ` // 创建者 CreatedBy int `json:"created_by" ` // 创建者
CreatedTime time.Time `json:"created_time" xorm:"created" ` // 创建时间 CreatedTime time.Time `json:"created_time" xorm:"created" ` // 创建时间
UpdatedBy int `json:"updated_by" ` // 更新者 UpdatedBy int `json:"updated_by" ` // 更新者
UpdatedTime time.Time `json:"updated_time" xorm:"updated" ` // 更新时间 UpdatedTime time.Time `json:"updated_time" xorm:"updated" ` // 更新时间
IsDeleted int `json:"is_deleted" xorm:"is_deleted"` // 是否删除 IsDeleted int `json:"is_deleted" xorm:"is_deleted"` // 是否删除
Phone string `json:"phone" xorm:"phone"` // 手机号 Phone string `json:"phone" xorm:"phone"` // 手机号
PwdLevel int `json:"pwd_level"` // 密码强度1低2中3高
PwdForceStatus int `json:"pwd_force_status"` // 密码强制修改状态0否1是
LastAccessTime time.Time `json:"last_access_time" xorm:"last_access_time"` // 用户最后访问时间
PwdUpdatedTime time.Time `json:"pwd_updated_time"` // 密码修改时间
} }
type SystemUserInfo struct { type SystemUserInfo struct {
Id int `json:"id" xorm:"pk autoincr" ` // id Id int `json:"id" xorm:"pk autoincr" ` // id
Name string `json:"name" ` // 名称 Name string `json:"name" ` // 名称
SystemAccount string `json:"system_account" ` // 账号 SystemAccount string `json:"system_account" ` // 账号
OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织 OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织
Password string `json:"password,omitempty"` // 密码 Password string `json:"password,omitempty"` // 密码
State int `json:"state" xorm:"state"` // 状态0禁用1启用 State int `json:"state" xorm:"state"` // 状态0禁用1启用
Logo string `json:"logo" xorm:"logo"` // 头像logo Logo string `json:"logo" xorm:"logo"` // 头像logo
IsDeleted int `json:"is_deleted" xorm:"is_deleted"` // 是否删除 IsDeleted int `json:"is_deleted" xorm:"is_deleted"` // 是否删除
Phone string `json:"phone" xorm:"phone"` // 手机号 Phone string `json:"phone" xorm:"phone"` // 手机号
PwdLevel int `json:"pwd_level"` // 密码强度1低2中3高
PwdForceStatus int `json:"pwd_force_status"` // 密码强制修改状态0否1是
LastAccessTime time.Time `json:"last_access_time" xorm:"last_access_time"` // 用户最后访问时间
PwdUpdatedTime time.Time `json:"pwd_updated_time"` // 密码修改时间
OrgName string `json:"org_name"` // 组织机构名称
} }
...@@ -18,6 +18,7 @@ type CreateSystemUserReq struct { ...@@ -18,6 +18,7 @@ type CreateSystemUserReq struct {
CreatedBy string `json:"created_by"` // 用户创建人 CreatedBy string `json:"created_by"` // 用户创建人
UpdatedBy string `json:"updated_by"` // 用户更新人 UpdatedBy string `json:"updated_by"` // 用户更新人
IsAdmin int `json:"is_admin"` // 用户类型 IsAdmin int `json:"is_admin"` // 用户类型
} }
type UpdateSystemUserReq struct { type UpdateSystemUserReq struct {
......
...@@ -9,7 +9,7 @@ type LogManagementRep struct { ...@@ -9,7 +9,7 @@ type LogManagementRep struct {
OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织 OrganizationId string `json:"organization_id" xorm:"organization_id"` // 所属组织
Name string `json:"name"` // 所属组织名称 Name string `json:"name"` // 所属组织名称
SystemAccount string `json:"system_account" xorm:"system_account"` // 系统账号 SystemAccount string `json:"system_account" xorm:"system_account"` // 系统账号
ContactPhone string `json:"contact_phone" xorm:"contact_phone"` // 联系人电话 Phone string `json:"phone" xorm:"phone"` // 联系人电话
//IsAdmin string `json:"is_admin" xorm:"is_admin"` // 用户类型 (1.业务系统账号 2.组织管理员账号 3.平台用户账号 4.超级管理员) //IsAdmin string `json:"is_admin" xorm:"is_admin"` // 用户类型 (1.业务系统账号 2.组织管理员账号 3.平台用户账号 4.超级管理员)
LastAccessTimes jsontime.Time `json:"-" xorm:"last_access_time"` // 用户最后访问时间 LastAccessTimes jsontime.Time `json:"-" xorm:"last_access_time"` // 用户最后访问时间
LastAccessTime jsontime.Time `json:"last_access_time" xorm:"-"` // 用户最后访问时间 LastAccessTime jsontime.Time `json:"last_access_time" xorm:"-"` // 用户最后访问时间
......
...@@ -40,5 +40,6 @@ type SystemMenuTreePer struct { ...@@ -40,5 +40,6 @@ type SystemMenuTreePer struct {
MenuId string `json:"menu_id" xorm:"menu_id"` //菜单id MenuId string `json:"menu_id" xorm:"menu_id"` //菜单id
PMenuId string `json:"p_menu_id" xorm:"p_menu_id"` //上级菜单id PMenuId string `json:"p_menu_id" xorm:"p_menu_id"` //上级菜单id
SystemType string `json:"system_type"` //系统类型 SystemType string `json:"system_type"` //系统类型
Source string `json:"source" xorm:"source"` //源
Children []SystemMenuTreePer `json:"children" xorm:"-"` Children []SystemMenuTreePer `json:"children" xorm:"-"`
} }
...@@ -121,3 +121,20 @@ func (r Redis) DelList(keys []string) error { ...@@ -121,3 +121,20 @@ func (r Redis) DelList(keys []string) error {
bmd := r.Conn.Del(keys...) bmd := r.Conn.Del(keys...)
return bmd.Err() return bmd.Err()
} }
func (r Redis) LPush(key string, value interface{}) error {
key = fmt.Sprintf("%s-%s", strings.ToUpper(r.Prefix), strings.ToUpper(key))
bmd := r.Conn.LPush(strings.ToUpper(key), value)
return bmd.Err()
}
func (r Redis) LRange(key string) (str []string, err error) {
key = fmt.Sprintf("%s-%s", strings.ToUpper(r.Prefix), strings.ToUpper(key))
return r.Conn.LRange(key, 0, -1).Result()
}
func (r Redis) LRem(key string, value interface{}) error {
key = fmt.Sprintf("%s-%s", strings.ToUpper(r.Prefix), strings.ToUpper(key))
bmd := r.Conn.LRem(key, 0, value)
return bmd.Err()
}
...@@ -111,44 +111,41 @@ func LogUserBehaviorDelete(c *gin.Context) { ...@@ -111,44 +111,41 @@ func LogUserBehaviorDelete(c *gin.Context) {
SendJsonResponse(c, nil, "删除成功") SendJsonResponse(c, nil, "删除成功")
} }
//用户账户审计列表 // 用户账户审计列表
//func LogUserAccountAuditList(c *gin.Context) { func LogUserAccountAuditList(c *gin.Context) {
// params := request.LogManagementListReq{} params := request.LogManagementListReq{}
// // 绑定分页数据 // 绑定分页数据
// if err := c.ShouldBindQuery(&params); err != nil { if err := c.ShouldBindQuery(&params); err != nil {
// SendJsonResponse(c, res.ParamsParserError.ErrorDetail(err), nil) SendJsonResponse(c, resp.InvalidParam.WithError(err), nil)
// return return
// } }
// // 分页数据初始化 limit page Offset svc := service.LogManagement{User: header.GetUser(c)}
// params.PageInfo = params.PageInfo.InitPage() list, count, err := svc.LogUserAccountAuditList(&params)
// svc := service.LogManagement{User: util.GetContextUser(c)} if err != nil {
// list, count, err := svc.LogUserAccountAuditList(&params) SendJsonResponse(c, err, nil)
// if err != nil { return
// SendJsonResponse(c, err, nil) }
// return SendJsonPageResponse(c, err, list, count)
// } }
// SendJsonPageResponse(c, err, list, count)
//} // 用户账户审计列表导出LogUserAccountAuditExport
// func LogUserAccountAuditExport(c *gin.Context) {
//// 用户账户审计列表导出LogUserAccountAuditExport params := request.LogManagementListReq{}
//func LogUserAccountAuditExport(c *gin.Context) { // 绑定分页数据
// params := request.LogManagementListReq{} if err := c.ShouldBindQuery(&params); err != nil {
// // 绑定分页数据 SendJsonResponse(c, resp.InvalidParam.WithError(err), nil)
// if err := c.ShouldBindQuery(&params); err != nil { return
// SendJsonResponse(c, res.ParamsParserError.ErrorDetail(err), nil) }
// return // 分页数据初始化 limit page Offset
// } svc := service.LogManagement{User: header.GetUser(c)}
// // 分页数据初始化 limit page Offset file, fileName, err := svc.LogUserAccountAuditExport(&params)
// params.PageInfo = params.PageInfo.InitPage() if err != nil {
// svc := service.LogManagement{User: util.GetContextUser(c)} SendJsonResponse(c, err, nil)
// file, fileName, err := svc.LogUserAccountAuditExport(&params) return
// if err != nil { }
// SendJsonResponse(c, err, nil) c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName)) //fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名
// return c.Writer.Header().Add("Content-Type", "application/octet-stream")
// } c.Writer.Header().Add("Content-Transfer-Encoding", "binary")
// c.Writer.Header().Add("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName)) //fmt.Sprintf("attachment; filename=%s", filename)对下载的文件重命名 _ = file.Write(c.Writer)
// c.Writer.Header().Add("Content-Type", "application/octet-stream")
// c.Writer.Header().Add("Content-Transfer-Encoding", "binary") }
// _ = file.Write(c.Writer)
//
//}
package controller package controller
import ( import (
"errors"
vd "github.com/bytedance/go-tagexpr/validator" vd "github.com/bytedance/go-tagexpr/validator"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/vo/request"
...@@ -8,9 +9,9 @@ import ( ...@@ -8,9 +9,9 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/service" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/service"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"go.uber.org/zap" "go.uber.org/zap"
"strconv" "strconv"
"time"
) )
func UserLogin(c *gin.Context) { func UserLogin(c *gin.Context) {
...@@ -48,7 +49,88 @@ func UserLogin(c *gin.Context) { ...@@ -48,7 +49,88 @@ func UserLogin(c *gin.Context) {
SendJsonResponse(c, resp.OK, msg) SendJsonResponse(c, resp.OK, msg)
} }
func UserLoginV2(c *gin.Context) {
userReq := request.UserReq{}
err := c.BindJSON(&userReq)
if err != nil {
SendJsonResponse(c, resp.InvalidParam.WithError(err), nil)
return
}
// 参数检测
if err = vd.Validate(userReq); err != nil {
SendJsonResponse(c, resp.InvalidParam.WithError(err), nil)
return
}
loginInf := service.UserSvc{SystemAccount: userReq.SystemAccount}
userInfo, err := loginInf.GetUserInfo("")
if err != nil {
SendJsonResponse(c, err, nil)
return
}
// 获取系统配置信息
op := service.SystemOptionsSvc{}
config, err := op.GetSystemOptions()
if err != nil {
SendJsonResponse(c, err, nil)
return
}
// 未开启是否启用登录配置时 只进行密码正确性校验 (admin 始终只进行密码校验)
upperMd5Pass, err := service.SolvePassword(userInfo.Id, userReq.Password)
if err != nil {
conf.Logger.Error("加密错误", zap.Error(err))
SendJsonResponse(c, err, nil)
return
}
if upperMd5Pass != userInfo.Password {
if config.LoginConfigState == 1 {
err := loginInf.UserLock(userInfo.Id, userInfo.Password, config)
if err != nil {
SendJsonResponse(c, err, nil)
return
}
err = errors.New("密码错误")
SendJsonResponse(c, err, nil)
return
}
loginInf.UserUnLock(userInfo.Id)
// TODO STEP2 用户和ip没有加入到访问规则登录不上提醒
if config.AccessRuleState == 1 {
ip := util.RemoteIp(c.Request)
svc := service.AccessRuleSvc{}
if errCode := svc.CheckIp(ip, userInfo.Id); errCode != nil {
SendJsonResponse(c, errCode, nil)
return
}
}
// 密码失效提醒
subDays := util.SubDays(time.Now(), userInfo.PwdUpdatedTime)
if config.PwdValidity-subDays <= 0 && config.PwdValidity != 0 && userInfo.PwdUpdatedTime.String()[:10] != "0001-01-01" {
SendJsonResponse(c, resp.FAIL.ErrorDetail(errors.New("密码已失效,请联系管理员修改密码!")), nil)
return
}
// 密码强弱提醒
if config.ForceUpdateState == 1 && config.MinPwdLevel > userInfo.PwdLevel {
SendJsonResponse(c, resp.FAIL.ErrorDetail(errors.New("密码强度弱,请联系管理员修改密码!")), nil)
return
}
lastLogin, msg, uuidStr, err := loginInf.LoginV2(userInfo)
if err != nil {
SendJsonResponse(c, err, "")
return
}
c.SetCookie(conf.CookieName, uuidStr, 1*60*60*24, "/", "", false, false)
c.SetCookie(conf.CookieNameLastLogin, lastLogin, 1*60*60*24, "/", "", false, false)
SendJsonResponse(c, resp.OK, msg)
}
}
func GetUserInfo(c *gin.Context) { func GetUserInfo(c *gin.Context) {
token, _ := c.Cookie(conf.CookieName) token, _ := c.Cookie(conf.CookieName)
conf.Logger.Info("当前token信息为", zap.String("bgToken", token)) conf.Logger.Info("当前token信息为", zap.String("bgToken", token))
header := c.GetHeader(conf.CookieName) header := c.GetHeader(conf.CookieName)
......
...@@ -31,12 +31,13 @@ func InitLogManagementRouter(e *gin.Engine) { ...@@ -31,12 +31,13 @@ func InitLogManagementRouter(e *gin.Engine) {
} }
//userAccountAudit := logger.Group("/userAccountAudit", header.SetContext) //userAccountAudit := logger.Group("/userAccountAudit", header.SetContext)
//{ userAccountAudit := logger.Group("/userAccountAudit")
// //用户账户审计: {
// userAccountAudit.GET("list", controller.LogUserAccountAuditList, header.AddLogMiddleware("用户账户审计", "/list", constant.OpTypeIntMap[constant.Find])) //用户账户审计列表 //用户账户审计:
// userAccountAudit.GET("list/export", controller.LogUserAccountAuditExport, header.AddLogMiddleware("用户账户审计", "/export", constant.OpTypeIntMap[constant.Export])) //用户账户审计列表导出 userAccountAudit.GET("list", controller.LogUserAccountAuditList, header.AddLogMiddleware("用户账户审计", "/list", constant.OpTypeIntMap[constant.Find])) //用户账户审计列表
// userAccountAudit.GET("list/export", controller.LogUserAccountAuditExport, header.AddLogMiddleware("用户账户审计", "/export", constant.OpTypeIntMap[constant.Export])) //用户账户审计列表导出
//}
}
} }
} }
package service
import (
"fmt"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/bean/entity"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/client"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"net"
"strings"
"time"
"github.com/go-redis/redis"
"github.com/spf13/cast"
"go.uber.org/zap"
)
type AccessRuleSvc struct {
}
// 校验用户访问的ip是否合法
func (r *AccessRuleSvc) CheckIp(ip string, userId int) error {
rcon, err := client.GetRedisClient()
if err != nil {
conf.Logger.Error("redis err", zap.Error(err))
return resp.RedisConnectError.ErrorDetail(err)
}
mode := 0
modeVal, err := rcon.Get(conf.Options.AccessRuleModeKey)
if err != nil {
if err == redis.Nil {
// 查询数据库
accessRuleMode, errCode := r.GetAccessRuleMode()
if errCode != nil {
conf.Logger.Error("db err", zap.Error(err))
return resp.DbSelectError.ErrorDetail(err)
}
mode = accessRuleMode
err = rcon.Set(conf.Options.AccessRuleModeKey, accessRuleMode, 60*time.Second)
if err != nil {
return err
}
} else {
conf.Logger.Error("redis err", zap.Error(err))
return resp.RedisExecError.ErrorDetail(err)
}
} else {
mode = cast.ToInt(modeVal)
}
switch mode {
case 0: // 访问规则模式关闭
return nil
case 1: // 黑名单模式
accessRules, errCode := r.GetAllAccessRules(1)
if errCode != nil {
conf.Logger.Error("db err", zap.Error(err))
return resp.DbSelectError.ErrorDetail(err)
}
//查询登录用户是否加入访问规则
ruleUserInfo, err := r.GetSystemRuleUser(userId)
if err != nil {
return resp.DbSelectError.ErrorDetail(err)
}
for i := range accessRules {
// 判断ip 是否合法
fmt.Println(accessRules[i].RuleDetail)
ruleArr := strings.Split(accessRules[i].RuleDetail, "\n")
for _, rule := range ruleArr {
//IP校验+用户是否加入访问规则
if r.checkIp(ip, strings.Trim(rule, " ")) == false && len(ruleUserInfo) > 0 {
conf.Logger.Error("访问规则error", zap.Error(err))
return resp.FAIL.ErrorDetail(fmt.Errorf("您的IP:%s不在访问白名单内,禁止访问,请联系管理员。", ip))
}
}
}
}
return nil
}
func (r *AccessRuleSvc) checkIp(targetIp, ipRule string) bool {
parseIP := net.ParseIP(ipRule)
if parseIP != nil {
return parseIP.String() == targetIp
} else {
_, ipNet, _ := net.ParseCIDR(ipRule)
if ipNet != nil {
return ipNet.Contains(net.ParseIP(targetIp))
}
}
return false
}
// 获取访问规则模式
func (r *AccessRuleSvc) GetAccessRuleMode() (int, error) {
db, err := client.GetDbClient()
if err != nil {
return 0, resp.DbConnectError.ErrorDetail(err)
}
var accessRuleMode int
_, err = db.Table("system_preference_config").Select("access_rule_state").Get(&accessRuleMode)
if err != nil {
return 0, resp.DbSelectError.ErrorDetail(err)
}
return accessRuleMode, nil
}
// 查询所有的访问规则
func (r *AccessRuleSvc) GetAllAccessRules(state int) ([]entity.SystemAccessRule, error) {
db, err := client.GetDbClient()
if err != nil {
return nil, resp.DbConnectError.ErrorDetail(err)
}
var ls []entity.SystemAccessRule
session := db.Table("system_access_rule").Where("rule_type = 1")
if state != 0 {
session.Where("state = ?", state)
}
if err := session.Find(&ls); err != nil {
return nil, resp.DbSelectError.ErrorDetail(err)
}
return ls, nil
}
// 查询用户维护访问规则
func (r *AccessRuleSvc) GetSystemRuleUser(userId int) ([]entity.SystemRuleUser, error) {
db, err := client.GetDbClient()
if err != nil {
return nil, resp.DbConnectError.ErrorDetail(err)
}
var ls []entity.SystemRuleUser
modelObj := db.Table("system_rule_user").Alias("sru")
modelObj.Join("INNER", []string{"system_access_rule", "sar"}, "sar.rule_id = sru.rule_id")
modelObj.Where("sru.user_id = ?", userId).And("sar.state = 1")
if err := modelObj.Find(&ls); err != nil {
return nil, resp.DbSelectError.ErrorDetail(err)
}
return ls, nil
}
...@@ -232,228 +232,131 @@ func (s *LogManagement) LogUserBehaviorDelete(ids []string) (err error) { ...@@ -232,228 +232,131 @@ func (s *LogManagement) LogUserBehaviorDelete(ids []string) (err error) {
return nil return nil
} }
//// LogUserAccountAuditList 行为日志列表 // LogUserAccountAuditList 行为日志列表
//func (s *LogManagement) LogUserAccountAuditList(params *request.LogManagementListReq) ([]response.LogManagementRep, int64, error) { func (s *LogManagement) LogUserAccountAuditList(params *request.LogManagementListReq) ([]response.LogManagementRep, int64, error) {
// var logManagementRep = []response.LogManagementRep{} var logManagementRep []response.LogManagementRep
// db, err := client.GetDbClient() db, err := client.GetDbClient()
// if err != nil { if err != nil {
// err = res.DbConnectError.ErrorDetail(err) err = resp.DbConnectError.ErrorDetail(err)
// return nil, 0, err return nil, 0, err
// } }
//
// modelObj := db.Table("system_user as u") modelObj := db.Table("system_user as u")
// modelObj.Join("left", "system_organization as org", "u.organization_id = org.organization_id"). modelObj.Join("left", "system_organization as org", "u.organization_id = org.organization_id").
// Select(`u.ID, Select(`u.id,
// system_account, u.system_account,
// contact_phone, u.phone,
// case is_admin when 1 then '业务系统账号' when 2 then '组织管理员账号' when 3 then '平台用户账号' when 4 then '超级管理员' end as is_admin, u.name,
// NAME, u.organization_id,
// u.organization_id, u.last_access_time,
// last_access_time, case u.pwd_level when 1 then '弱' when 2 then '中' when 3 then '强' end as pwd_level,
// case pwd_level when 1 then '弱' when 2 then '中' when 3 then '强' end as pwd_level, u.pwd_updated_time,
// pwd_updated_time, date_part('day', now()-u.pwd_updated_time)as pwd_is_used ,
// date_part('day', now()-pwd_updated_time)as pwd_is_used , u.created_time `)
// u.created_time `)
// // 条件查询
// // 条件查询 if params.Search != "" {
// if params.Search != "" { keyword := util.SpecialEscape(params.Search)
// keyword := util.SpecialEscape(params.Search) modelObj.Where("system_account like ? or phone like ? or NAME like ?", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
// modelObj.Where("system_account ilike ? or contact_phone ilike ? or NAME ilike ?", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") }
// } // 上次访问时间
// // 用户类型 if params.StartAt != "" && params.EndAt != "" {
// if params.IsAdmin != 0 { applyEndTime, timeErr := time.Parse(jsontime.LocalDateFormat, params.EndAt)
// modelObj.Where("is_admin = ?", params.IsAdmin) if timeErr != nil {
// } conf.Logger.Error("时间转换错误", zap.Error(timeErr))
// // 上次访问时间 return nil, 0, resp.DbSelectError.ErrorDetail(timeErr)
// if params.StartAt != "" && params.EndAt != "" { }
// applyEndTime, timeErr := time.Parse(jsonTime.LocalDateFormat, params.EndAt) EndAt := applyEndTime.AddDate(0, 0, 1).Format(jsontime.LocalDateFormat)
// if timeErr != nil { modelObj.Where("last_access_time >= ? and last_access_time < ?", params.StartAt, EndAt)
// conf.Logger.Error("时间转换错误", zap.Error(timeErr)) }
// return nil, 0, res.DataFailError.ErrorDetail(timeErr) // 活跃度 1: 低 2:中 3: 高
// } if params.Active != 0 {
// EndAt := applyEndTime.AddDate(0, 0, 1).Format(jsonTime.LocalDateFormat) switch params.Active {
// modelObj.Where("last_access_time >= ? and last_access_time < ?", params.StartAt, EndAt) case 1:
// } modelObj.Where("last_access_time <= now()-interval '1 month'")
// // 活跃度 1: 低 2:中 3: 高 case 2:
// if params.Active != 0 { modelObj.Where("last_access_time < now()-interval '1 week'").And("last_access_time > now()-interval '1 month'")
// switch params.Active { case 3:
// case 1: modelObj.Where("last_access_time >= now()-interval '1 week'")
// modelObj.Where("last_access_time <= now()-interval '1 month'") }
// case 2: }
// modelObj.Where("last_access_time < now()-interval '1 week'").And("last_access_time > now()-interval '1 month'") // 密码强度
// case 3: if params.PwdLevel != 0 {
// modelObj.Where("last_access_time >= now()-interval '1 week'") modelObj.Where("pwd_level = ? ", params.PwdLevel)
// } }
// } count, err := modelObj.OrderBy("last_access_time desc").Limit(params.GetPageSize(), params.GetOffset()).FindAndCount(&logManagementRep)
// // 密码强度 if err != nil {
// if params.PwdLevel != 0 { conf.Logger.Error("查询用户账户审计列表失败", zap.Error(err))
// modelObj.Where("pwd_level = ? ", params.PwdLevel) err = resp.DbSelectError.ErrorDetail(errors.New("查询用户账户审计列表失败"))
// } return nil, 0, err
// count, err := modelObj.OrderBy("last_access_time desc").Limit(int(params.Limit), int(params.Offset)).FindAndCount(&logManagementRep) }
// if err != nil { for k := range logManagementRep {
// conf.Logger.Error("查询用户账户审计列表失败", zap.Error(err)) active := getActivity(time.Time(logManagementRep[k].LastAccessTimes))
// err = res.DbSelectError.ErrorDetail(errors.New("查询用户账户审计列表失败")) logManagementRep[k].Active = active
// return nil, 0, err logManagementRep[k].LastAccessTime = logManagementRep[k].LastAccessTimes
// } }
// for k := range logManagementRep {
// // lastAccessTime := cast.ToTime(logManagementRep[k].LastAccessTimes) return logManagementRep, count, nil
// active := getActivity(logManagementRep[k].LastAccessTimes) }
// logManagementRep[k].Active = active
// logManagementRep[k].LastAccessTime = jsonTime.JsonTime(logManagementRep[k].LastAccessTimes) func getActivity(date time.Time) string {
// } // dates := cast.ToTime(date)
// var (
// return logManagementRep, count, nil lastAccess = date.Unix()
//} pastWeek = time.Now().AddDate(0, 0, -7).Unix()
// pastMonth = time.Now().AddDate(0, -1, 0).Unix()
//func getActivity(date time.Time) string { )
// // dates := cast.ToTime(date) if lastAccess >= pastWeek {
// var ( return "高"
// lastAccess = date.Unix() }
// pastWeek = time.Now().AddDate(0, 0, -7).Unix() if lastAccess < pastWeek && lastAccess > pastMonth {
// pastMonth = time.Now().AddDate(0, -1, 0).Unix() return "中"
// ) }
// if lastAccess >= pastWeek { if lastAccess <= pastMonth {
// return "高" return "低"
// } }
// if lastAccess < pastWeek && lastAccess > pastMonth { return "不活跃"
// return "中" }
// }
// if lastAccess <= pastMonth { // LogUserAccountAuditExport 行为日志导出
// return "低" func (s *LogManagement) LogUserAccountAuditExport(params *request.LogManagementListReq) (xlFile *xlsx.File, fileName string, err error) {
// } xlFile = xlsx.NewFile()
// return "不活跃" sheet, err := xlFile.AddSheet("sheet")
//} if err != nil {
// conf.Logger.Error("xlFile.AddSheet err", zap.Error(err))
//// LogUserAccountAuditExport 行为日志导出 return
//func (s *LogManagement) LogUserAccountAuditExport(params *request.LogManagementListReq) (xlFile *xlsx.File, fileName string, err error) { }
// xlFile = xlsx.NewFile() titleRow := sheet.AddRow()
// sheet, err := xlFile.AddSheet("sheet") tmp := []string{
// if err != nil { "序号", "账号", "手机号", "所属组织", "上次访问时间", "活跃度", "密码强度", "密码使用时长/天", "创建时间",
// conf.Logger.Error("xlFile.AddSheet err", zap.Error(err)) }
// return xlsRow2 := tools.NewRow(titleRow, tmp)
// } err = xlsRow2.SetRowTitle()
// titleRow := sheet.AddRow() if err != nil {
// tmp := []string{ return
// "序号", "账号", "手机号", "用户类型", "所属组织", "上次访问时间", "活跃度", "密码强度", "密码使用时长/天", "创建时间", }
// } //params.Page = 0
// xlsRow2 := tools.NewRow(titleRow, tmp) //params.PageSize = 20000
// err = xlsRow2.SetRowTitle() list, total, err := s.LogUserAccountAuditList(params)
// if err != nil { if total == 0 {
// return err = errors.New("没有可导出的数据")
// } return
// params.Page = 0 } else {
// params.Limit = 20000 fileName = "用户账号审计" + ".xlsx"
// list, total, err := s.LogUserAccountAuditList(params) }
// if total == 0 { id := 0
// err = errors.New("没有可导出的数据") for _, detail := range list {
// return id += 1
// } else { currentRow := sheet.AddRow()
// fileName = "用户账号审计" + ".xlsx" var tmp = []string{
// } strconv.Itoa(id), detail.SystemAccount, detail.Phone, detail.Name, detail.LastAccessTime.String(),
// id := 0 detail.Active, detail.PwdLevel, strconv.Itoa(detail.PwdIsUsed), detail.CreatedTime.String(),
// for _, detail := range list { }
// id += 1 newRow := tools.NewRow(currentRow, tmp)
// currentRow := sheet.AddRow() err := newRow.GenerateRow()
// var tmp = []string{ if err != nil {
// strconv.Itoa(id), detail.SystemAccount, detail.ContactPhone, detail.IsAdmin, detail.Name, cast.ToString(detail.LastAccessTime), return nil, "", err
// detail.Active, detail.PwdLevel, strconv.Itoa(detail.PwdIsUsed), cast.ToString(detail.CreatedTime), }
// } }
// newRow := tools.NewRow(currentRow, tmp) return
// err := newRow.GenerateRow() }
// if err != nil {
// return nil, "", err
// }
// }
// return
//}
//
//// 用户行为审计列表
//func (s *LogManagement) LogUserBehaviorListEs(params *request.LogUserBehaviorListReq) (list []response.SystemUserBehaviorList, total int64, err error) {
// es, err := client.GetEsConnection(conf.EsDoc.Index)
// if err != nil {
// return nil, 0, res.DbConnectError.ErrorDetail(err)
// }
// // boolQuery 可用于组合查询
// boolQuery := elastic.NewBoolQuery()
// // 条件查询
// if params.Search != "" {
// keyword := util.SpecialEscape(params.Search)
// boolQuery.Filter(
// elastic.NewBoolQuery().Should(
// elastic.NewWildcardQuery("system_account.keyword", fmt.Sprintf("*%s*", keyword)),
// elastic.NewWildcardQuery("system_module.keyword", fmt.Sprintf("*%s*", keyword)),
// elastic.NewWildcardQuery("operate_addr.keyword", fmt.Sprintf("*%s*", keyword)),
// ))
// }
// // 用户类型
// if params.IsAdmin != 0 {
// boolQuery.Filter(elastic.NewMatchQuery("is_admin", params.IsAdmin))
// }
// // 上次访问时间
// if params.StartAt != "" && params.EndAt != "" {
// applyEndTime, timeErr := time.Parse(jsonTime.LocalDateFormatEs, params.EndAt)
// if timeErr != nil {
// conf.Logger.Error("时间转换错误", zap.Error(timeErr))
// return nil, 0, res.DataFailError.ErrorDetail(timeErr)
// }
// EndAt := applyEndTime.AddDate(0, 0, 1).Format(jsonTime.LocalDateFormatEs)
// boolQuery.Filter(elastic.NewRangeQuery("created_time").Gte(params.StartAt))
// boolQuery.Filter(elastic.NewRangeQuery("created_time").Lt(EndAt))
// }
// // 操作类型
// if params.OperateType != "" {
// boolQuery.Filter(elastic.NewMatchQuery("operate_type", params.OperateType))
// }
// // 请求方式
// if params.ReqMethod != 0 {
// boolQuery.Filter(elastic.NewMatchQuery("req_method", params.ReqMethod))
// }
// // 操作状态
// if params.OperateStatus != 0 {
// boolQuery.Filter(elastic.NewMatchQuery("operate_status", params.OperateStatus))
// }
// searchResult, err := es.Conn.Search().
// Index(conf.EsDoc.Index).
// Query(boolQuery).
// SortWithInfo(elastic.SortInfo{Field: "created_time_unix", Ascending: false, UnmappedType: "keyword"}).
// From(int((params.Page - 1) * params.Limit)).Size(cast.ToInt(params.Limit)).
// Pretty(true).
// Do(context.Background())
// if err != nil {
// conf.Logger.Error("查询用户行为审计列表失败", zap.Error(err))
// return nil, 0, res.DbSelectError.ErrorDetail(err)
// }
// bytes, err := json.Marshal(searchResult)
// if err != nil {
// conf.Logger.Error("json.Marshal序列化用户行为信息失败", zap.Error(err))
// return nil, 0, res.JsonMarshalError.ErrorDetail(err)
// }
// resultMap := map[string]interface{}{}
// err = json.Unmarshal(bytes, &resultMap)
// if err != nil {
// conf.Logger.Error("序列化用户行为信息失败", zap.Error(err))
// return nil, 0, res.JsonMarshalError.ErrorDetail(err)
// }
// data, has := resultMap["hits"]
// esData := response.BehaviorEsListInfo{}
// if has {
// bytes, err := json.Marshal(data)
// if err != nil {
// conf.Logger.Error("序列化用户行为信息失败", zap.Error(err))
// return nil, 0, err
// }
// err = json.Unmarshal(bytes, &esData)
// if err != nil {
// conf.Logger.Error("序列化用户行为信息失败", zap.Error(err))
// return nil, 0, err
// }
// for k, v := range esData.Hits {
// esData.Hits[k].Source.Id = v.Id
// esData.Hits[k].Source.Xh = (params.Page) * int64(k+1)
// list = append(list, esData.Hits[k].Source)
// }
// }
// total = cast.ToInt64(esData.Total["value"])
// return list, total, nil
//}
//
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/tools" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/tools"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp" "gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/resp"
"strconv"
"image/color" "image/color"
"strings" "strings"
...@@ -30,6 +31,36 @@ type UserSvc struct { ...@@ -30,6 +31,36 @@ type UserSvc struct {
PassWord string PassWord string
} }
// 获取用户信息(登录前)
func (u *UserSvc) GetUserInfo(phone string) (userInfo entity.SystemUserInfo, err error) {
db, err := client.GetDbClient()
if err != nil {
return userInfo, resp.DbConnectError.ErrorDetail(err)
}
var userRole []entity.SystemUserInfo
// 查询用户
userModel := db.Table("system_user")
userModel.Join("LEFT", []string{"system_user_role", "sur"}, "sur.user_id = system_user.id")
userModel.Join("LEFT", []string{"system_role", "sr"}, "sur.role_id = sr.role_id")
userModel.Join("LEFT", []string{"system_organization", "so"}, "so.organization_id = system_user.organization_id")
userModel.Select("system_user.*,so.name as org_name")
if phone == "" {
userModel.Where("system_account = ?", u.SystemAccount)
} else {
userModel.Where("system_user.phone = ?", phone)
}
err = userModel.Where("system_user.state = 1").Find(&userRole)
if err != nil {
return userInfo, resp.DbSelectError.ErrorDetail(err)
}
if len(userRole) == 0 && phone == "" {
return userInfo, resp.FAIL.WithError(errors.New("该账户未启用,不能登录"))
} else if len(userRole) == 0 && phone != "" {
return userInfo, resp.FAIL.WithError(errors.New("手机号未注册!"))
}
return userInfo, nil
}
func (u *UserSvc) Login() (msg string, uuidStr string, last_login string, err error) { func (u *UserSvc) Login() (msg string, uuidStr string, last_login string, err error) {
db, err := client.GetDbClient() db, err := client.GetDbClient()
if err != nil { if err != nil {
...@@ -241,13 +272,13 @@ func (u *UserSvc) VerifyCaptcha(id, value string) (err error) { ...@@ -241,13 +272,13 @@ func (u *UserSvc) VerifyCaptcha(id, value string) (err error) {
} }
// 用户锁定(此逻辑包含锁定规则以及锁定key) // 用户锁定(此逻辑包含锁定规则以及锁定key)
func (u *UserSvc) UserLock(systemId, pwd string, config *entity.SystemPreferenceConfig) (err error) { func (u *UserSvc) UserLock(userId int, pwd string, config *entity.SystemPreferenceConfig) (err error) {
r, err := client.GetRedisClient() r, err := client.GetRedisClient()
if err != nil { if err != nil {
return resp.RedisConnectError.ErrorDetail(err) return resp.RedisConnectError.ErrorDetail(err)
} }
startLockKey := fmt.Sprintf("%s-%s", client.RULEKEY, systemId) startLockKey := fmt.Sprintf("%s-%v", client.RULEKEY, userId)
lockSystemKey := fmt.Sprintf("%s-%s", client.LOCKKEY, systemId) lockSystemKey := fmt.Sprintf("%s-%v", client.LOCKKEY, userId)
errorNum, err := r.Get(startLockKey) errorNum, err := r.Get(startLockKey)
if err != nil && err != redis.Nil { if err != nil && err != redis.Nil {
conf.Logger.Error("获取密码插入次数失败", zap.Error(err)) conf.Logger.Error("获取密码插入次数失败", zap.Error(err))
...@@ -280,27 +311,28 @@ func (u *UserSvc) UserLock(systemId, pwd string, config *entity.SystemPreference ...@@ -280,27 +311,28 @@ func (u *UserSvc) UserLock(systemId, pwd string, config *entity.SystemPreference
} }
} }
// 判断是否输错密码 // 判断是否输错密码
h := md5.New()
_, err = h.Write([]byte(strings.ToUpper(systemId + "-" + u.PassWord))) incr, err := r.Incr(startLockKey)
if err != nil { if err != nil {
conf.Logger.Error("加密错误", zap.Error(err)) conf.Logger.Error("写入错误次数失败", zap.Error(err))
return err return err
} }
upperMd5Pass := strings.ToUpper(hex.EncodeToString(h.Sum(nil))) conf.Logger.Info("当前错误次数为", zap.Int64("incr", incr))
if upperMd5Pass != pwd { if int(incr) >= config.LoginPwdError {
incr, err := r.Incr(startLockKey) err = r.Set(lockSystemKey, 0, time.Duration(config.LoginLockTime)*time.Minute)
if err != nil { if err != nil {
conf.Logger.Error("写入错误次数失败", zap.Error(err))
return err return err
} }
conf.Logger.Info("当前错误次数为", zap.Int64("incr", incr)) }
if int(incr) >= config.LoginPwdError { return fmt.Errorf("请正确输入密码,连续%d次输错密码,账号将被锁定,还可重试%d次", incr, config.LoginPwdError-cast.ToInt(incr))
err = r.Set(lockSystemKey, 0, time.Duration(config.LoginLockTime)*time.Minute)
if err != nil { }
return err
} func (u *UserSvc) UserUnLock(userId int) error {
} startLockKey := fmt.Sprintf("%s-%v", client.RULEKEY, userId)
return fmt.Errorf("请正确输入密码,连续%d次输错密码,账号将被锁定,还可重试%d次", incr, config.LoginPwdError-cast.ToInt(incr)) r, err := client.GetRedisClient()
if err != nil {
return resp.RedisConnectError.ErrorDetail(err)
} }
// 密码正确 删除 锁定文件 // 密码正确 删除 锁定文件
if err := r.Del(startLockKey); err != nil { if err := r.Del(startLockKey); err != nil {
...@@ -309,3 +341,81 @@ func (u *UserSvc) UserLock(systemId, pwd string, config *entity.SystemPreference ...@@ -309,3 +341,81 @@ func (u *UserSvc) UserLock(systemId, pwd string, config *entity.SystemPreference
} }
return nil return nil
} }
// 登录
func (u *UserSvc) LoginV2(userInfo entity.SystemUserInfo) (last_login_time, msg string, uuidStr string, err error) {
redisCli, err := client.GetRedisClient()
if err != nil {
return "", "", "", resp.RedisConnectError.ErrorDetail(err)
}
// TODO 用户数据、登录时间存入redis
last_login_time, uuidStr, err = u.SaveUserInfo(userInfo, redisCli)
if err != nil {
conf.Logger.Error("保存用户数据失败", zap.Error(err))
return "", "", "", resp.RedisExecError.ErrorDetail(err)
}
msg = "登录成功"
conf.Logger.Info("登录成功", zap.String("msg", msg))
//go func() {
// // 最后心跳时间
// finalHeartBeatMap := map[string]interface{}{
// "final_heartbeat_unix": time.Now().UnixNano() / 1e6,
// "final_heartbeat_flag": false,
// }
// finalHeartBeatByte, _ := json.Marshal(finalHeartBeatMap)
// redisCli.HSet(conf.FinalHeartBeatUnixKey, userInfo.Id, string(finalHeartBeatByte))
//}()
return
}
// 保存用户信息
func (u *UserSvc) SaveUserInfo(userInfo entity.SystemUserInfo, r client.Redis) (last_login, uuidStr string, err error) {
uu := uuid.NewV4()
uuidStr = uu.String()
// 存入redis
b, err := json.Marshal(userInfo)
op := SystemOptionsSvc{}
config, err := op.GetSystemOptions()
expireTime := time.Duration(config.SessionValidity)
if err != nil {
return "", "", err
}
err = r.Set(uuidStr, string(b), time.Minute*expireTime)
if err != nil {
conf.Logger.Error("保存用户数据失败", zap.Error(err))
return "", "", err
}
// 登录时间计录在map
loginMap := make(map[string]string, 0)
cont, _ := r.Get("LOGIN-TIME")
if cont != "" {
err = json.Unmarshal([]byte(cont), &loginMap)
if err != nil {
return "", "", err
}
}
now := time.Now().Format(conf.LocalDateTimeFormat)
if _, ok := loginMap[u.SystemAccount]; ok {
last_login = loginMap[u.SystemAccount]
} else {
last_login = now
}
loginMap[u.SystemAccount] = now
a, err := json.Marshal(loginMap)
if err != nil {
return "", "", err
}
err = r.Set("LOGIN-TIME", string(a), -1)
if err != nil {
conf.Logger.Error("登录失败", zap.Error(err))
return "", "", err
}
// 保存用户id以及token信息
err = r.LPush(strconv.Itoa(userInfo.Id), uuidStr)
if err != nil {
conf.Logger.Error("保存用户信息失败", zap.Error(err))
return "", "", err
}
return last_login, uuidStr, nil
}
...@@ -140,8 +140,16 @@ func (o *User) OrgAddUser(input request.OrgUserInput) error { ...@@ -140,8 +140,16 @@ func (o *User) OrgAddUser(input request.OrgUserInput) error {
conf.Logger.Error("密码处理出错", zap.Error(err)) conf.Logger.Error("密码处理出错", zap.Error(err))
return nil, resp.DbInsertError.ErrorDetail(err) return nil, resp.DbInsertError.ErrorDetail(err)
} }
_, err = s.Table("system_user").Where("id = ?", userModel.Id).Update(map[string]string{ pwdLevel, err := util.GetPwdLevel(input.Password)
"password": upperMd5Pass, if err != nil {
conf.Logger.Error("密码处理出错", zap.Error(err))
return nil, resp.DbInsertError.ErrorDetail(err)
}
_, err = s.Table("system_user").Where("id = ?", userModel.Id).Update(map[string]interface{}{
"password": upperMd5Pass,
"pwd_level": pwdLevel,
"pwd_updated_time": jsontime.Time(time.Now()),
"pwd_force_status": 0,
}) })
if err != nil { if err != nil {
conf.Logger.Error("密码处理出错", zap.Error(err)) conf.Logger.Error("密码处理出错", zap.Error(err))
...@@ -346,10 +354,18 @@ func SystemUserEditPassword(params request.SystemUserEditPasswordReq) (err error ...@@ -346,10 +354,18 @@ func SystemUserEditPassword(params request.SystemUserEditPasswordReq) (err error
if err != nil { if err != nil {
return return
} }
pwdLevel, err := util.GetPwdLevel(params.Password)
if err != nil {
return
}
SystemUser := entity.SystemUser{} SystemUser := entity.SystemUser{}
SystemUser.Password = password SystemUser.Password = password
SystemUser.PwdLevel = pwdLevel
SystemUser.PwdForceStatus = 0
SystemUser.PwdUpdatedTime = time.Now()
_, err = db.Where("id=?", oldSystemUser.Id).Where("is_deleted = 0").Update(&SystemUser) _, err = db.Where("id=?", oldSystemUser.Id).Where("is_deleted = 0").Cols("password,pwd_level,pwd_force_status,pwd_updated_time").
Update(&SystemUser)
if err != nil { if err != nil {
conf.Logger.Error("修改系统账户失败", zap.Error(err)) conf.Logger.Error("修改系统账户失败", zap.Error(err))
err = resp.DbUpdateError.ErrorDetail(errors.New("修改系统账户失败")) err = resp.DbUpdateError.ErrorDetail(errors.New("修改系统账户失败"))
...@@ -359,32 +375,40 @@ func SystemUserEditPassword(params request.SystemUserEditPasswordReq) (err error ...@@ -359,32 +375,40 @@ func SystemUserEditPassword(params request.SystemUserEditPasswordReq) (err error
} }
// ResetSystemUserPassword 批量重置密码 // ResetSystemUserPassword 批量重置密码
func ResetSystemUserPassword(params request.ResetSystemUserPasswordReq) (err error) { func ResetSystemUserPassword(params request.ResetSystemUserPasswordReq) error {
db, err := client.GetDbClient() db, err := client.GetDbClient()
if err != nil { if err != nil {
err = resp.DbConnectError.ErrorDetail(err) err = resp.DbConnectError.ErrorDetail(err)
return return err
} }
str, EncryptErr := util.EncryptPwd(defaultPassword) str, EncryptErr := util.EncryptPwd(defaultPassword)
if EncryptErr != nil { if EncryptErr != nil {
err = resp.DbUpdateError.ErrorDetail(err) err = resp.DbUpdateError.ErrorDetail(err)
return err
} }
for _, v := range params.Ids { for _, v := range params.Ids {
password, SolvePwdErr := SolvePassword(v, str) password, SolvePwdErr := SolvePassword(v, str)
if SolvePwdErr != nil { if SolvePwdErr != nil {
return SolvePwdErr return SolvePwdErr
} }
updateData := entity.SystemUser{} pwdLevel, err := util.GetPwdLevel(password)
updateData.Password = password if err != nil {
_, err = db.Where("id=?", v).Update(&updateData) return err
}
SystemUser := entity.SystemUser{}
SystemUser.Password = password
SystemUser.PwdLevel = pwdLevel
SystemUser.PwdForceStatus = 0
SystemUser.PwdUpdatedTime = time.Now()
_, err = db.Where("id=?", v).Cols("password,pwd_level,pwd_force_status,pwd_updated_time").Update(&SystemUser)
if err != nil { if err != nil {
conf.Logger.Error("重置账户密码失败", zap.Error(err)) conf.Logger.Error("重置账户密码失败", zap.Error(err))
err = resp.DbUpdateError.ErrorDetail(errors.New("重置账户密码失败")) err = resp.DbUpdateError.ErrorDetail(errors.New("重置账户密码失败"))
return return err
} }
} }
return return nil
} }
// SolvePassword 密码处理 // SolvePassword 密码处理
......
...@@ -9,9 +9,13 @@ ...@@ -9,9 +9,13 @@
package util package util
import ( import (
"errors"
"fmt"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"net/http" "net/http"
"regexp" "regexp"
"strings" "strings"
"time"
"unsafe" "unsafe"
"github.com/Luzifer/go-openssl/v4" "github.com/Luzifer/go-openssl/v4"
...@@ -41,6 +45,58 @@ func DecryptPwd(pwd string) (str string, err error) { ...@@ -41,6 +45,58 @@ func DecryptPwd(pwd string) (str string, err error) {
return string(dec), err return string(dec), err
} }
type StrReplaceStruct struct {
CapitalLetter int `json:"capital_letter"`
LowercaseLetters int `json:"lowercase_letters"`
Number int `json:"number"`
OtherString int `json:"other_string"`
}
// 获取密码强度
func GetPwdLevel(pwd string) (level int, err error) {
password, err := DecryptPwd(pwd)
if err != nil {
return 0, err
}
conf.Logger.Info(fmt.Sprintf("解析密码为: %s", password))
var (
groupCount int
arrayGroup []int
)
arrayGroup = append(arrayGroup, StrReplaceAllString(password).CapitalLetter, StrReplaceAllString(password).LowercaseLetters, StrReplaceAllString(password).Number, StrReplaceAllString(password).OtherString)
for _, v := range arrayGroup {
if v > 0 {
groupCount += 1
}
}
if groupCount == 0 {
return 0, errors.New("密码非法!")
} else if groupCount == 1 {
level = 1
} else if groupCount == 2 {
level = 2
} else if groupCount >= 3 {
level = 3
}
return level, nil
}
func StrReplaceAllString(s2 string) (strReplace StrReplaceStruct) {
for i := strReplace.OtherString; i < len(s2); i++ {
switch {
case 64 < s2[i] && s2[i] < 91:
strReplace.CapitalLetter += 1
case 96 < s2[i] && s2[i] < 123:
strReplace.LowercaseLetters += 1
case 47 < s2[i] && s2[i] < 58:
strReplace.Number += 1
default:
strReplace.OtherString += 1
}
}
return strReplace
}
func EncryptPwd(password string) (pwd string, err error) { func EncryptPwd(password string) (pwd string, err error) {
passphrase := "swuE9cmCZQwrkYRV" passphrase := "swuE9cmCZQwrkYRV"
ecs, err := OpenSslManager.EncryptBytes(passphrase, []byte(password), openssl.BytesToKeyMD5) ecs, err := OpenSslManager.EncryptBytes(passphrase, []byte(password), openssl.BytesToKeyMD5)
...@@ -72,3 +128,26 @@ func SpecialEscape(keyword string) string { ...@@ -72,3 +128,26 @@ func SpecialEscape(keyword string) string {
func Bytes2Str(b []byte) string { func Bytes2Str(b []byte) string {
return *(*string)(unsafe.Pointer(&b)) return *(*string)(unsafe.Pointer(&b))
} }
// 计算日期差(t1>t2)
func SubDays(t1, t2 time.Time) (day int) {
swap := false
if t1.Unix() < t2.Unix() {
t_ := t1
t1 = t2
t2 = t_
swap = true
}
day = int(t1.Sub(t2).Hours() / 24)
// 计算在被24整除外的时间是否存在跨自然日
if int(t1.Sub(t2).Milliseconds())%86400000 > int(86400000-t2.Unix()%86400000) {
day += 1
}
if swap {
day = -day
}
if day < 0 {
day = 0
}
return
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment