🎨 新增ip检测配置功能
This commit is contained in:
@@ -55,7 +55,7 @@ func (*AppUserApi) Login(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := appUserService.Login(p)
|
user, isNewUser, err := appUserService.Login(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.FailWithMessage("登录失败", ctx)
|
r.FailWithMessage("登录失败", ctx)
|
||||||
return
|
return
|
||||||
@@ -104,6 +104,7 @@ func (*AppUserApi) Login(ctx *gin.Context) {
|
|||||||
"User": user,
|
"User": user,
|
||||||
"Token": token,
|
"Token": token,
|
||||||
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||||
|
"IsNewUser": isNewUser,
|
||||||
}, "登录成功", ctx)
|
}, "登录成功", ctx)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
|
global.GVA_LOG.Error("设置登录状态失败!", zap.Error(err))
|
||||||
@@ -127,7 +128,7 @@ func (*AppUserApi) WechatLogin(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
user, err := appUserService.WechatLogin(info)
|
user, isNewUser, err := appUserService.WechatLogin(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.FailWithMessage("登录失败:"+err.Error(), ctx)
|
r.FailWithMessage("登录失败:"+err.Error(), ctx)
|
||||||
return
|
return
|
||||||
@@ -158,17 +159,29 @@ func (*AppUserApi) WechatLogin(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
adcodes := utils.CheckIPInAdcodes(loginLog.Address)
|
// 判断是否为新用户
|
||||||
if !adcodes {
|
if isNewUser {
|
||||||
global.GVA_LOG.Warn("异常登录地址", zap.String("address", loginLog.Address), zap.Uint("userId", user.ID))
|
ipCheckStatus := false
|
||||||
|
|
||||||
user.Status = 0
|
err = global.GVA_DB.Model(&user2.IpCheck{}).Select("status").Scan(&ipCheckStatus).Error
|
||||||
if err := global.GVA_DB.Save(&user).Error; err != nil {
|
if err != nil {
|
||||||
global.GVA_LOG.Error("禁用用户失败!", zap.Error(err))
|
global.GVA_LOG.Error("获取IP检测状态失败", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Banned("用户已被禁用", ctx)
|
if ipCheckStatus {
|
||||||
return
|
adcodes := utils.CheckIPInAdcodes(loginLog.Address)
|
||||||
|
if !adcodes {
|
||||||
|
global.GVA_LOG.Warn("异常登录地址", zap.String("address", loginLog.Address), zap.Uint("userId", user.ID))
|
||||||
|
|
||||||
|
user.Status = 0
|
||||||
|
if err := global.GVA_DB.Save(&user).Error; err != nil {
|
||||||
|
global.GVA_LOG.Error("禁用用户失败!", zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Banned("用户已被禁用", ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成token
|
// 生成token
|
||||||
@@ -195,6 +208,7 @@ func (*AppUserApi) WechatLogin(ctx *gin.Context) {
|
|||||||
"User": user,
|
"User": user,
|
||||||
"Token": token,
|
"Token": token,
|
||||||
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
"ExpiresAt": claims.RegisteredClaims.ExpiresAt.Unix() * 1000,
|
||||||
|
"IsNewUser": isNewUser,
|
||||||
}, "登录成功", ctx)
|
}, "登录成功", ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"git.echol.cn/loser/lckt/model/app"
|
"git.echol.cn/loser/lckt/model/app"
|
||||||
common "git.echol.cn/loser/lckt/model/common/request"
|
common "git.echol.cn/loser/lckt/model/common/request"
|
||||||
r "git.echol.cn/loser/lckt/model/common/response"
|
r "git.echol.cn/loser/lckt/model/common/response"
|
||||||
|
"git.echol.cn/loser/lckt/model/user"
|
||||||
"git.echol.cn/loser/lckt/model/user/request"
|
"git.echol.cn/loser/lckt/model/user/request"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@@ -272,3 +273,57 @@ func (a *UserApi) SetTeacherExpectRate(context *gin.Context) {
|
|||||||
r.OkWithMessage("修改讲师信息成功", context)
|
r.OkWithMessage("修改讲师信息成功", context)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===========================IP检测配置==========================
|
||||||
|
|
||||||
|
// SetIpCheckConfig 设置IP检测配置
|
||||||
|
func (a *UserApi) SetIpCheckConfig(ctx *gin.Context) {
|
||||||
|
var p user.IpCheck
|
||||||
|
if err := ctx.ShouldBind(&p); err != nil {
|
||||||
|
r.FailWithMessage(err.Error(), ctx)
|
||||||
|
global.GVA_LOG.Error("参数错误,设置IP检测配置失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
config, err := userService.SetIpConfig(p)
|
||||||
|
if err != nil {
|
||||||
|
r.FailWithMessage("设置IP检测配置失败", ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.OkWithData(config, ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIpCheckConfig 获取IP检测配置
|
||||||
|
func (a *UserApi) GetIpCheckConfig(ctx *gin.Context) {
|
||||||
|
config, err := userService.GetIpConfig()
|
||||||
|
if err != nil {
|
||||||
|
r.FailWithMessage("获取IP检测配置失败", ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.OkWithData(config, ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIpCheckStatus 获取IP检测状态
|
||||||
|
func (a *UserApi) GetIpCheckStatus(ctx *gin.Context) {
|
||||||
|
status, err := userService.GetIpStatus()
|
||||||
|
if err != nil {
|
||||||
|
r.FailWithMessage("获取IP检测状态失败", ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.OkWithDetailed(status, "获取IP检测状态成功", ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIpCheckStatus 设置IP检测状态
|
||||||
|
func (a *UserApi) SetIpCheckStatus(ctx *gin.Context) {
|
||||||
|
var p user.IpCheck
|
||||||
|
if err := ctx.ShouldBind(&p); err != nil {
|
||||||
|
r.FailWithMessage(err.Error(), ctx)
|
||||||
|
global.GVA_LOG.Error("参数错误,设置IP检测状态失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
status, err := userService.SetIpStatus(p.Status)
|
||||||
|
if err != nil {
|
||||||
|
r.FailWithMessage("设置IP检测状态失败", ctx)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.OkWithDetailed(status, "设置IP检测状态成功", ctx)
|
||||||
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ func RegisterTables() {
|
|||||||
app.BalanceLog{},
|
app.BalanceLog{},
|
||||||
app.With{},
|
app.With{},
|
||||||
app.Domain{},
|
app.Domain{},
|
||||||
|
user.IpCheck{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.GVA_LOG.Error("register table failed", zap.Error(err))
|
global.GVA_LOG.Error("register table failed", zap.Error(err))
|
||||||
|
|||||||
@@ -11,3 +11,11 @@ type UpdateTeacherVipPriceBatch struct {
|
|||||||
Ids []uint `json:"ids" form:"ids" vd:"@:len($)>0; msg:'请选择要修改的讲师VIP'"`
|
Ids []uint `json:"ids" form:"ids" vd:"@:len($)>0; msg:'请选择要修改的讲师VIP'"`
|
||||||
Price float64 `json:"price" form:"price" vd:"@:len($)>0; msg:'请输入讲师VIP价格'"` // 讲师VIP价格
|
Price float64 `json:"price" form:"price" vd:"@:len($)>0; msg:'请输入讲师VIP价格'"` // 讲师VIP价格
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IpCheckConfigReq struct {
|
||||||
|
IpAddrs []string `json:"ip_addrs" form:"ip_addrs" vd:"@:len($)>0; msg:'请输入要检测的IP地址列表'"` // IP地址列表
|
||||||
|
}
|
||||||
|
|
||||||
|
type IpCheckStatus struct {
|
||||||
|
Status bool `json:"status" form:"status"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ type UserRouter struct{}
|
|||||||
// InitUserRouter 初始化 用户相关 路由信息
|
// InitUserRouter 初始化 用户相关 路由信息
|
||||||
func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
||||||
userRouter := Router.Group("app_user").Use(middleware.OperationRecord())
|
userRouter := Router.Group("app_user").Use(middleware.OperationRecord())
|
||||||
|
publicRouter := PublicRouter.Group("app_user")
|
||||||
{
|
{
|
||||||
userRouter.GET("list", userApi.GetUserList) // 获取用户列表
|
userRouter.GET("list", userApi.GetUserList) // 获取用户列表
|
||||||
userRouter.PUT("setBalance", userApi.SetBalance) // 更新用户余额
|
userRouter.PUT("setBalance", userApi.SetBalance) // 更新用户余额
|
||||||
@@ -34,4 +35,12 @@ func (s *UserRouter) InitUserRouter(Router *gin.RouterGroup, PublicRouter *gin.R
|
|||||||
userRouter.DELETE("teacher_vip", teacherVipApi.DeleteTeacherVip) // 删除讲师VIP
|
userRouter.DELETE("teacher_vip", teacherVipApi.DeleteTeacherVip) // 删除讲师VIP
|
||||||
userRouter.PUT("/teacher_vip/price", teacherVipApi.UpdatePriceBatch) // 批量设置讲师课程价格
|
userRouter.PUT("/teacher_vip/price", teacherVipApi.UpdatePriceBatch) // 批量设置讲师课程价格
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
userRouter.PUT("ipStatus", userApi.SetIpCheckStatus) // 设置ip检测状态
|
||||||
|
userRouter.PUT("ipCon", userApi.SetIpCheckConfig) // 设置ip检测配置
|
||||||
|
publicRouter.GET("ipCon", userApi.GetIpCheckConfig) // 获取ip检测配置
|
||||||
|
userRouter.GET("ipStatus", userApi.GetIpCheckStatus) // 获取ip检测状态
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ import (
|
|||||||
type AppUserService struct{}
|
type AppUserService struct{}
|
||||||
|
|
||||||
// Login 用户登录
|
// Login 用户登录
|
||||||
func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, err error) {
|
func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, isNewUser bool, err error) {
|
||||||
|
isNewUser = false
|
||||||
// 1. 判断用户是否存在
|
// 1. 判断用户是否存在
|
||||||
var count int64
|
var count int64
|
||||||
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).Count(&count).Error
|
err = global.GVA_DB.Model(&user.User{}).Where("phone = ?", req.Phone).Count(&count).Error
|
||||||
@@ -30,6 +31,7 @@ func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, err e
|
|||||||
|
|
||||||
// 2. 如果用户不存在,则创建用户
|
// 2. 如果用户不存在,则创建用户
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
|
isNewUser = true
|
||||||
user := user.User{
|
user := user.User{
|
||||||
Phone: req.Phone,
|
Phone: req.Phone,
|
||||||
UserLabel: 1,
|
UserLabel: 1,
|
||||||
@@ -51,7 +53,8 @@ func (u *AppUserService) Login(req request.CodeLoginReq) (users user.User, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WechatLogin 微信登录
|
// WechatLogin 微信登录
|
||||||
func (u *AppUserService) WechatLogin(info *providers.User) (users user.User, err error) {
|
func (u *AppUserService) WechatLogin(info *providers.User) (users user.User, isNewUser bool, err error) {
|
||||||
|
isNewUser = false
|
||||||
openID := info.GetOpenID()
|
openID := info.GetOpenID()
|
||||||
var count int64
|
var count int64
|
||||||
if openID == "" {
|
if openID == "" {
|
||||||
@@ -76,7 +79,7 @@ func (u *AppUserService) WechatLogin(info *providers.User) (users user.User, err
|
|||||||
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
|
global.GVA_LOG.Error("创建用户失败", zap.Error(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return newUser, nil
|
return newUser, true, nil
|
||||||
} else {
|
} else {
|
||||||
err = global.GVA_DB.Where("open_id = ?", openID).First(&users).Error
|
err = global.GVA_DB.Where("open_id = ?", openID).First(&users).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -392,3 +392,51 @@ func (u *UserService) SetTeacherExpectRate(p request.SetTeacherInfo) (err error)
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *UserService) SetIpConfig(p user.IpCheck) (user.IpCheck, error) {
|
||||||
|
p.ID = 1
|
||||||
|
err := global.GVA_DB.Save(&p).Error
|
||||||
|
if err != nil {
|
||||||
|
global.GVA_LOG.Error("修改IP检测配置失败", zap.Error(err))
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserService) GetIpConfig() (ipConfig user.IpCheck, err error) {
|
||||||
|
ipConfig.ID = 1
|
||||||
|
err = global.GVA_DB.First(&ipConfig).Error
|
||||||
|
if err != nil {
|
||||||
|
global.GVA_LOG.Error("获取IP检测配置失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserService) SetIpStatus(status bool) (bool, error) {
|
||||||
|
var ipConfig user.IpCheck
|
||||||
|
ipConfig.ID = 1
|
||||||
|
err := global.GVA_DB.First(&ipConfig).Error
|
||||||
|
if err != nil {
|
||||||
|
global.GVA_LOG.Error("获取IP检测配置失败", zap.Error(err))
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
ipConfig.Status = status
|
||||||
|
err = global.GVA_DB.Save(&ipConfig).Error
|
||||||
|
if err != nil {
|
||||||
|
global.GVA_LOG.Error("修改IP检测状态失败", zap.Error(err))
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return status, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UserService) GetIpStatus() (status bool, err error) {
|
||||||
|
var ipConfig user.IpCheck
|
||||||
|
err = global.GVA_DB.Where("id = 1").First(&ipConfig).Error
|
||||||
|
if err != nil {
|
||||||
|
global.GVA_LOG.Error("获取IP检测配置失败", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
status = ipConfig.Status
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
31
utils/ip.go
31
utils/ip.go
@@ -3,6 +3,9 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"git.echol.cn/loser/lckt/global"
|
||||||
|
user2 "git.echol.cn/loser/lckt/model/user"
|
||||||
|
"go.uber.org/zap"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,13 +17,6 @@ type ipAdcodeResp struct {
|
|||||||
} `json:"adcode"`
|
} `json:"adcode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// adcodes 是允许的地区编码列表
|
|
||||||
var adcodes = []string{
|
|
||||||
"重庆",
|
|
||||||
"海南",
|
|
||||||
"广东",
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetIPAdcode(ip string) string {
|
func GetIPAdcode(ip string) string {
|
||||||
url := fmt.Sprintf("https://api.vore.top/api/IPdata?ip=%s", ip)
|
url := fmt.Sprintf("https://api.vore.top/api/IPdata?ip=%s", ip)
|
||||||
client := &http.Client{Timeout: 5 * time.Second}
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
@@ -38,6 +34,27 @@ func GetIPAdcode(ip string) string {
|
|||||||
|
|
||||||
// CheckIPInAdcodes 检测用户IP是否在指定的地区编码范围内
|
// CheckIPInAdcodes 检测用户IP是否在指定的地区编码范围内
|
||||||
func CheckIPInAdcodes(ipAdcode string) bool {
|
func CheckIPInAdcodes(ipAdcode string) bool {
|
||||||
|
// 查询IP配置
|
||||||
|
ipCon := user2.IpCheck{}
|
||||||
|
err := global.GVA_DB.First(&ipCon).Error
|
||||||
|
if err != nil {
|
||||||
|
global.GVA_LOG.Error("获取IP配置失败", zap.Error(err))
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 如果IP检测未启用,直接返回true
|
||||||
|
if !ipCon.Status {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// 解析允许的地区编码列表
|
||||||
|
var adcodes []string
|
||||||
|
// 通过逗号分隔
|
||||||
|
for _, code := range strings.Split(ipCon.Addrs, ",") {
|
||||||
|
trimmed := strings.TrimSpace(code)
|
||||||
|
if trimmed != "" {
|
||||||
|
adcodes = append(adcodes, trimmed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lower := strings.ToLower(ipAdcode)
|
lower := strings.ToLower(ipAdcode)
|
||||||
for _, code := range adcodes {
|
for _, code := range adcodes {
|
||||||
// 检测是否包含
|
// 检测是否包含
|
||||||
|
|||||||
Reference in New Issue
Block a user