add comment verification

This commit is contained in:
landaiqing
2024-09-26 01:13:06 +08:00
parent 97175c3d67
commit 372835296d
14 changed files with 228 additions and 98 deletions

View File

@@ -239,12 +239,12 @@ func (CaptchaAPI) GenerateClickShapeCaptcha(c *gin.Context) {
result.OkWithData(bt, c) result.OkWithData(bt, c)
} }
// GenerateSlideBasicCaptData 生成点击形状基础验证码 // GenerateSlideBasicCaptData 滑块基础验证码
// @Summary 生成点击形状基础验证码 // @Summary 滑块基础验证码
// @Description 生成点击形状基础验证码 // @Description 滑块基础验证码
// @Tags 点击形状验证码 // @Tags 滑块基础验证码
// @Success 200 {string} json // @Success 200 {string} json
// @Router /api/captcha/shape/check [get] // @Router /api/captcha/slide/generate [get]
func (CaptchaAPI) GenerateSlideBasicCaptData(c *gin.Context) { func (CaptchaAPI) GenerateSlideBasicCaptData(c *gin.Context) {
captData, err := global.SlideCaptcha.Generate() captData, err := global.SlideCaptcha.Generate()
if err != nil { if err != nil {
@@ -266,70 +266,27 @@ func (CaptchaAPI) GenerateSlideBasicCaptData(c *gin.Context) {
return return
} }
key := helper.StringToMD5(string(dotsByte)) key := helper.StringToMD5(string(dotsByte))
err = redis.Set(key, dotsByte, time.Minute).Err() err = redis.Set(constant.CommentSubmitCaptchaRedisKey+key, dotsByte, time.Minute).Err()
if err != nil { if err != nil {
result.FailWithNull(c) result.FailWithNull(c)
return return
} }
bt := map[string]interface{}{ bt := map[string]interface{}{
"key": key, "key": key,
"image": masterImageBase64, "image": masterImageBase64,
"tile": tileImageBase64, "thumb": tileImageBase64,
"tile_width": blockData.Width, "thumb_width": blockData.Width,
"tile_height": blockData.Height, "thumb_height": blockData.Height,
"tile_x": blockData.TileX, "thumb_x": blockData.TileX,
"tile_y": blockData.TileY, "thumb_y": blockData.TileY,
} }
result.OkWithData(bt, c) result.OkWithData(bt, c)
} }
// CheckSlideData 验证点击形状验证码 // GenerateSlideRegionCaptData 生成滑动区域形状验证码
// @Summary 验证点击形状验证码 // @Summary 生成滑动区域形状验证码
// @Description 验证点击形状验证码 // @Description 生成滑动区域形状验证码
// @Tags 点击形状验证码 // @Tags 生成滑动区域形状验证码
// @Param point query string true "点击坐标"
// @Param key query string true "验证码key"
// @Success 200 {string} json
// @Router /api/captcha/shape/slide/check [get]
func (CaptchaAPI) CheckSlideData(c *gin.Context) {
point := c.Query("point")
key := c.Query("key")
if point == "" || key == "" {
result.FailWithNull(c)
return
}
cacheDataByte, err := redis.Get(key).Bytes()
if len(cacheDataByte) == 0 || err != nil {
result.FailWithNull(c)
return
}
src := strings.Split(point, ",")
var dct *slide.Block
if err := json.Unmarshal(cacheDataByte, &dct); err != nil {
result.FailWithNull(c)
return
}
chkRet := false
if 2 == len(src) {
sx, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[0]), 64)
sy, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[1]), 64)
chkRet = slide.CheckPoint(int64(sx), int64(sy), int64(dct.X), int64(dct.Y), 4)
}
if chkRet {
result.OkWithMessage("success", c)
return
}
result.FailWithMessage("fail", c)
}
// GenerateSlideRegionCaptData 生成点击形状验证码
// @Summary 生成点击形状验证码
// @Description 生成点击形状验证码
// @Tags 点击形状验证码
// @Success 200 {string} json // @Success 200 {string} json
// @Router /api/captcha/shape/slide/region/get [get] // @Router /api/captcha/shape/slide/region/get [get]
func (CaptchaAPI) GenerateSlideRegionCaptData(c *gin.Context) { func (CaptchaAPI) GenerateSlideRegionCaptData(c *gin.Context) {
@@ -371,3 +328,46 @@ func (CaptchaAPI) GenerateSlideRegionCaptData(c *gin.Context) {
} }
result.OkWithData(bt, c) result.OkWithData(bt, c)
} }
// CheckSlideData 验证滑动验证码
// @Summary 验证滑动验证码
// @Description 验证滑动验证码
// @Tags 验证滑动验证码
// @Param point query string true "点击坐标"
// @Param key query string true "验证码key"
// @Success 200 {string} json
// @Router /api/captcha/shape/slide/check [get]
func (CaptchaAPI) CheckSlideData(c *gin.Context) {
point := c.Query("point")
key := c.Query("key")
if point == "" || key == "" {
result.FailWithNull(c)
return
}
cacheDataByte, err := redis.Get(key).Bytes()
if len(cacheDataByte) == 0 || err != nil {
result.FailWithNull(c)
return
}
src := strings.Split(point, ",")
var dct *slide.Block
if err := json.Unmarshal(cacheDataByte, &dct); err != nil {
result.FailWithNull(c)
return
}
chkRet := false
if 2 == len(src) {
sx, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[0]), 64)
sy, _ := strconv.ParseFloat(fmt.Sprintf("%v", src[1]), 64)
chkRet = slide.CheckPoint(int64(sx), int64(sy), int64(dct.X), int64(dct.Y), 4)
}
if chkRet {
result.OkWithMessage("success", c)
return
}
result.FailWithMessage("fail", c)
}

View File

@@ -30,9 +30,15 @@ import (
func (CommentAPI) CommentSubmit(c *gin.Context) { func (CommentAPI) CommentSubmit(c *gin.Context) {
commentRequest := dto.CommentRequest{} commentRequest := dto.CommentRequest{}
if err := c.ShouldBindJSON(&commentRequest); err != nil { if err := c.ShouldBindJSON(&commentRequest); err != nil {
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
return return
} }
// 验证校验
res := utils.CheckSlideData(commentRequest.Point, commentRequest.Key)
if !res {
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaVerifyError"), c)
return
}
if len(commentRequest.Images) > 3 { if len(commentRequest.Images) > 3 {
result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c) result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c)
return return
@@ -148,7 +154,12 @@ func (CommentAPI) ReplySubmit(c *gin.Context) {
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
return return
} }
// 验证校验
res := utils.CheckSlideData(replyCommentRequest.Point, replyCommentRequest.Key)
if !res {
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaVerifyError"), c)
return
}
if len(replyCommentRequest.Images) > 3 { if len(replyCommentRequest.Images) > 3 {
result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c) result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c)
return return
@@ -270,7 +281,12 @@ func (CommentAPI) ReplyReplySubmit(c *gin.Context) {
result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c)
return return
} }
// 验证校验
res := utils.CheckSlideData(replyReplyRequest.Point, replyReplyRequest.Key)
if !res {
result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaVerifyError"), c)
return
}
if len(replyReplyRequest.Images) > 3 { if len(replyReplyRequest.Images) > 3 {
result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c) result.FailWithMessage(ginI18n.MustGetMessage(c, "TooManyImages"), c)
return return
@@ -394,7 +410,12 @@ func (CommentAPI) CommentList(c *gin.Context) {
// 查询评论列表 // 查询评论列表
query, u := gplus.NewQuery[model.ScaCommentReply]() query, u := gplus.NewQuery[model.ScaCommentReply]()
page := gplus.NewPage[model.ScaCommentReply](commentListRequest.Page, commentListRequest.Size) page := gplus.NewPage[model.ScaCommentReply](commentListRequest.Page, commentListRequest.Size)
query.Eq(&u.TopicId, commentListRequest.TopicId).Eq(&u.CommentType, enum.COMMENT).OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.ReplyCount).OrderByDesc(&u.CreatedTime) if commentListRequest.IsHot {
query.OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.ReplyCount)
} else {
query.OrderByDesc(&u.CommentOrder).OrderByDesc(&u.CreatedTime)
}
query.Eq(&u.TopicId, commentListRequest.TopicId).Eq(&u.CommentType, enum.COMMENT)
page, pageDB := gplus.SelectPage(page, query) page, pageDB := gplus.SelectPage(page, query)
if pageDB.Error != nil { if pageDB.Error != nil {
global.LOG.Errorln(pageDB.Error) global.LOG.Errorln(pageDB.Error)
@@ -455,7 +476,7 @@ func (CommentAPI) CommentList(c *gin.Context) {
// 查询评论图片信息 // 查询评论图片信息
go func() { go func() {
defer wg.Done() defer wg.Done()
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) // 设置超时2秒 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) // 设置超时2秒
defer cancel() defer cancel()
cursor, err := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").Find(ctx, bson.M{"comment_id": bson.M{"$in": commentIds}}) cursor, err := global.MongoDB.Database(global.CONFIG.MongoDB.DB).Collection("comment_images").Find(ctx, bson.M{"comment_id": bson.M{"$in": commentIds}})
@@ -563,7 +584,7 @@ func (CommentAPI) ReplyList(c *gin.Context) {
} }
query, u := gplus.NewQuery[model.ScaCommentReply]() query, u := gplus.NewQuery[model.ScaCommentReply]()
page := gplus.NewPage[model.ScaCommentReply](replyListRequest.Page, replyListRequest.Size) page := gplus.NewPage[model.ScaCommentReply](replyListRequest.Page, replyListRequest.Size)
query.Eq(&u.TopicId, replyListRequest.TopicId).Eq(&u.ReplyId, replyListRequest.CommentId).Eq(&u.CommentType, enum.REPLY).OrderByDesc(&u.CommentOrder).OrderByDesc(&u.Likes).OrderByDesc(&u.CreatedTime) query.Eq(&u.TopicId, replyListRequest.TopicId).Eq(&u.ReplyId, replyListRequest.CommentId).Eq(&u.CommentType, enum.REPLY).OrderByDesc(&u.Likes).OrderByAsc(&u.CreatedTime)
page, pageDB := gplus.SelectPage(page, query) page, pageDB := gplus.SelectPage(page, query)
if pageDB.Error != nil { if pageDB.Error != nil {
global.LOG.Errorln(pageDB.Error) global.LOG.Errorln(pageDB.Error)

View File

@@ -6,6 +6,8 @@ type CommentRequest struct {
UserID string `json:"user_id" binding:"required"` UserID string `json:"user_id" binding:"required"`
TopicId string `json:"topic_id" binding:"required"` TopicId string `json:"topic_id" binding:"required"`
Author string `json:"author" binding:"required"` Author string `json:"author" binding:"required"`
Key string `json:"key" binding:"required"`
Point []int64 `json:"point" binding:"required"`
} }
type ReplyCommentRequest struct { type ReplyCommentRequest struct {
Content string `json:"content" binding:"required"` Content string `json:"content" binding:"required"`
@@ -15,6 +17,8 @@ type ReplyCommentRequest struct {
ReplyId int64 `json:"reply_id" binding:"required"` ReplyId int64 `json:"reply_id" binding:"required"`
ReplyUser string `json:"reply_user" binding:"required"` ReplyUser string `json:"reply_user" binding:"required"`
Author string `json:"author" binding:"required"` Author string `json:"author" binding:"required"`
Key string `json:"key" binding:"required"`
Point []int64 `json:"point" binding:"required"`
} }
type ReplyReplyRequest struct { type ReplyReplyRequest struct {
@@ -26,6 +30,8 @@ type ReplyReplyRequest struct {
ReplyId int64 `json:"reply_id" binding:"required"` ReplyId int64 `json:"reply_id" binding:"required"`
ReplyUser string `json:"reply_user" binding:"required"` ReplyUser string `json:"reply_user" binding:"required"`
Author string `json:"author" binding:"required"` Author string `json:"author" binding:"required"`
Key string `json:"key" binding:"required"`
Point []int64 `json:"point" binding:"required"`
} }
type CommentListRequest struct { type CommentListRequest struct {
@@ -33,6 +39,7 @@ type CommentListRequest struct {
TopicId string `json:"topic_id" binding:"required"` TopicId string `json:"topic_id" binding:"required"`
Page int `json:"page" default:"1"` Page int `json:"page" default:"1"`
Size int `json:"size" default:"5"` Size int `json:"size" default:"5"`
IsHot bool `json:"is_hot" default:"true"`
} }
type ReplyListRequest struct { type ReplyListRequest struct {
UserID string `json:"user_id" binding:"required"` UserID string `json:"user_id" binding:"required"`

View File

@@ -11,6 +11,7 @@ import (
"schisandra-cloud-album/api/user_api/dto" "schisandra-cloud-album/api/user_api/dto"
"schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/constant"
"schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/redis"
"schisandra-cloud-album/common/result"
"schisandra-cloud-album/global" "schisandra-cloud-album/global"
"schisandra-cloud-album/model" "schisandra-cloud-album/model"
"schisandra-cloud-album/service" "schisandra-cloud-album/service"
@@ -39,10 +40,11 @@ var script = `
` `
func HandleLoginResponse(c *gin.Context, uid string) { func HandleLoginResponse(c *gin.Context, uid string) {
res, data := HandelUserLogin(uid) res, data := HandelUserLogin(uid, c)
if !res { if !res {
return return
} }
tokenData, err := json.Marshal(data) tokenData, err := json.Marshal(data)
if err != nil { if err != nil {
global.LOG.Error(err) global.LOG.Error(err)
@@ -55,7 +57,7 @@ func HandleLoginResponse(c *gin.Context, uid string) {
} }
// HandelUserLogin 处理用户登录 // HandelUserLogin 处理用户登录
func HandelUserLogin(userId string) (bool, map[string]interface{}) { func HandelUserLogin(userId string, c *gin.Context) (bool, result.Response) {
// 使用goroutine生成accessToken // 使用goroutine生成accessToken
accessTokenChan := make(chan string) accessTokenChan := make(chan string)
errChan := make(chan error) errChan := make(chan error)
@@ -86,7 +88,7 @@ func HandelUserLogin(userId string) (bool, map[string]interface{}) {
case accessToken = <-accessTokenChan: case accessToken = <-accessTokenChan:
case err = <-errChan: case err = <-errChan:
global.LOG.Error(err) global.LOG.Error(err)
return false, nil return false, result.Response{}
} }
select { select {
case refreshToken = <-refreshTokenChan: case refreshToken = <-refreshTokenChan:
@@ -99,7 +101,10 @@ func HandelUserLogin(userId string) (bool, map[string]interface{}) {
ExpiresAt: expiresAt, ExpiresAt: expiresAt,
UID: &userId, UID: &userId,
} }
wrong := utils.SetSession(c, "user", data)
if wrong != nil {
return false, result.Response{}
}
// 使用goroutine将数据存入redis // 使用goroutine将数据存入redis
redisErrChan := make(chan error) redisErrChan := make(chan error)
go func() { go func() {
@@ -115,13 +120,13 @@ func HandelUserLogin(userId string) (bool, map[string]interface{}) {
redisErr := <-redisErrChan redisErr := <-redisErrChan
if redisErr != nil { if redisErr != nil {
global.LOG.Error(redisErr) global.LOG.Error(redisErr)
return false, nil return false, result.Response{}
} }
responseData := map[string]interface{}{ responseData := result.Response{
"code": 0, Data: data,
"message": "success", Message: "success",
"data": data, Code: 200,
"success": true, Success: true,
} }
return true, responseData return true, responseData
} }

View File

@@ -1,6 +1,7 @@
package oauth_api package oauth_api
import ( import (
"encoding/gob"
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/ArtisanCloud/PowerLibs/v3/http/helper" "github.com/ArtisanCloud/PowerLibs/v3/http/helper"
@@ -47,7 +48,7 @@ func (OAuthAPI) CallbackNotify(c *gin.Context) {
return "error" return "error"
} }
key := strings.TrimPrefix(msg.EventKey, "qrscene_") key := strings.TrimPrefix(msg.EventKey, "qrscene_")
res := wechatLoginHandler(msg.FromUserName, key) res := wechatLoginHandler(msg.FromUserName, key, c)
if !res { if !res {
return messages.NewText(ginI18n.MustGetMessage(c, "LoginFailed")) return messages.NewText(ginI18n.MustGetMessage(c, "LoginFailed"))
} }
@@ -69,7 +70,7 @@ func (OAuthAPI) CallbackNotify(c *gin.Context) {
println(err.Error()) println(err.Error())
return "error" return "error"
} }
res := wechatLoginHandler(msg.FromUserName, msg.EventKey) res := wechatLoginHandler(msg.FromUserName, msg.EventKey, c)
if !res { if !res {
return messages.NewText(ginI18n.MustGetMessage(c, "LoginFailed")) return messages.NewText(ginI18n.MustGetMessage(c, "LoginFailed"))
} }
@@ -165,7 +166,7 @@ func (OAuthAPI) GetTempQrCode(c *gin.Context) {
} }
// wechatLoginHandler 微信登录处理 // wechatLoginHandler 微信登录处理
func wechatLoginHandler(openId string, clientId string) bool { func wechatLoginHandler(openId string, clientId string, c *gin.Context) bool {
if openId == "" { if openId == "" {
return false return false
} }
@@ -257,7 +258,7 @@ func wechatLoginHandler(openId string, clientId string) bool {
// 异步处理用户登录 // 异步处理用户登录
resChan := make(chan bool, 1) resChan := make(chan bool, 1)
go func() { go func() {
res := handelUserLogin(*addUser.UID, clientId) res := handelUserLogin(*addUser.UID, clientId, c)
resChan <- res resChan <- res
}() }()
@@ -271,7 +272,7 @@ func wechatLoginHandler(openId string, clientId string) bool {
tx.Commit() tx.Commit()
return true return true
} else { } else {
res := handelUserLogin(*authUserSocial.UserID, clientId) res := handelUserLogin(*authUserSocial.UserID, clientId, c)
if !res { if !res {
return false return false
} }
@@ -280,7 +281,7 @@ func wechatLoginHandler(openId string, clientId string) bool {
} }
// handelUserLogin 处理用户登录 // handelUserLogin 处理用户登录
func handelUserLogin(userId string, clientId string) bool { func handelUserLogin(userId string, clientId string, c *gin.Context) bool {
resultChan := make(chan bool, 1) resultChan := make(chan bool, 1)
go func() { go func() {
@@ -312,6 +313,12 @@ func handelUserLogin(userId string, clientId string) bool {
resultChan <- false resultChan <- false
return return
} }
gob.Register(dto.ResponseData{})
wrong := utils.SetSession(c, "user", data)
if wrong != nil {
resultChan <- false
return
}
// gws方式发送消息 // gws方式发送消息
err = websocket_api.Handler.SendMessageToClient(clientId, tokenData) err = websocket_api.Handler.SendMessageToClient(clientId, tokenData)
if err != nil { if err != nil {

View File

@@ -1,6 +1,7 @@
package user_api package user_api
import ( import (
"encoding/gob"
"errors" "errors"
ginI18n "github.com/gin-contrib/i18n" ginI18n "github.com/gin-contrib/i18n"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -332,6 +333,7 @@ func handelUserLogin(user model.ScaAuthUser, autoLogin bool, c *gin.Context) {
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c)
return return
} }
gob.Register(dto.ResponseData{})
err = utils.SetSession(c, "user", data) err = utils.SetSession(c, "user", data)
if err != nil { if err != nil {
result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c)

View File

@@ -1,6 +1,7 @@
package constant package constant
const ( const (
// 登录相关的redis key
UserLoginSmsRedisKey = "user:sms:" UserLoginSmsRedisKey = "user:sms:"
UserLoginTokenRedisKey = "user:token:" UserLoginTokenRedisKey = "user:token:"
UserLoginCaptchaRedisKey = "user:captcha:" UserLoginCaptchaRedisKey = "user:captcha:"
@@ -8,3 +9,8 @@ const (
UserLoginQrcodeRedisKey = "user:qrcode:" UserLoginQrcodeRedisKey = "user:qrcode:"
UserSessionRedisKey = "user:session:" UserSessionRedisKey = "user:session:"
) )
// 登录之后
const (
CommentSubmitCaptchaRedisKey = "comment:submit:captcha:"
)

View File

@@ -16,6 +16,7 @@ import (
func InitCaptcha() { func InitCaptcha() {
initRotateCaptcha() initRotateCaptcha()
initsSlideCaptcha()
} }
// initTextCaptcha 初始化点选验证码 // initTextCaptcha 初始化点选验证码

View File

@@ -1,4 +1,3 @@
welcome = "hello"
NotFoundUser = "User not found" NotFoundUser = "User not found"
DeletedSuccess = "deleted successfully!" DeletedSuccess = "deleted successfully!"
DeletedFailed = "delete failed!" DeletedFailed = "delete failed!"
@@ -73,4 +72,5 @@ ImageSaveError = "image save error!"
CommentLikeSuccess = "comment like success!" CommentLikeSuccess = "comment like success!"
CommentLikeFailed = "comment like failed!" CommentLikeFailed = "comment like failed!"
CommentDislikeSuccess = "comment dislike success!" CommentDislikeSuccess = "comment dislike success!"
CommentDislikeFailed = "comment dislike failed!" CommentDislikeFailed = "comment dislike failed!"
CaptchaVerifyError = "captcha error!"

View File

@@ -1,4 +1,3 @@
welcome = "欢迎"
NotFoundUser = "未找到用户!" NotFoundUser = "未找到用户!"
DeletedSuccess = "删除成功!" DeletedSuccess = "删除成功!"
DeletedFailed = "删除失败!" DeletedFailed = "删除失败!"
@@ -73,4 +72,5 @@ ImageSaveError = "图片保存错误!"
CommentLikeSuccess = "评论点赞成功!" CommentLikeSuccess = "评论点赞成功!"
CommentLikeFailed = "评论点赞失败!" CommentLikeFailed = "评论点赞失败!"
CommentDislikeSuccess = "评论取消点赞成功!" CommentDislikeSuccess = "评论取消点赞成功!"
CommentDislikeFailed = "评论取消点赞失败!" CommentDislikeFailed = "评论取消点赞失败!"
CaptchaVerifyError = "验证失败!"

View File

@@ -9,6 +9,13 @@ var captchaApi = api.Api.CaptchaApi
func CaptchaRouter(router *gin.RouterGroup) { func CaptchaRouter(router *gin.RouterGroup) {
group := router.Group("/captcha") group := router.Group("/captcha")
group.GET("/rotate/get", captchaApi.GenerateRotateCaptcha) group.GET("/rotate/get", captchaApi.GenerateRotateCaptcha)
group.POST("/rotate/check", captchaApi.CheckRotateData) group.POST("/rotate/check", captchaApi.CheckRotateData)
} }
// CaptchaRouterAuth 需要鉴权的路由
func CaptchaRouterAuth(router *gin.RouterGroup) {
group := router.Group("/captcha")
group.GET("/slide/generate", captchaApi.GenerateSlideBasicCaptData)
}

View File

@@ -52,10 +52,11 @@ func InitRouter() *gin.Engine {
middleware.CasbinMiddleware(), middleware.CasbinMiddleware(),
) )
{ {
modules.UserRouterAuth(authGroup) // 注册鉴权路由 modules.UserRouterAuth(authGroup) // 注册鉴权路由
modules.RoleRouter(authGroup) // 注册角色路由 modules.RoleRouter(authGroup) // 注册角色路由
modules.PermissionRouter(authGroup) // 注册权限路由 modules.PermissionRouter(authGroup) // 注册权限路由
modules.CommentRouter(authGroup) // 注册评论路由 modules.CommentRouter(authGroup) // 注册评论路由
modules.CaptchaRouterAuth(authGroup) // 注册验证码路由
} }
return router return router

66
utils/check_captcha.go Normal file
View File

@@ -0,0 +1,66 @@
package utils
import (
"encoding/json"
"fmt"
"github.com/wenlng/go-captcha/v2/rotate"
"github.com/wenlng/go-captcha/v2/slide"
"schisandra-cloud-album/common/constant"
"schisandra-cloud-album/common/redis"
"schisandra-cloud-album/global"
"strconv"
)
// CheckSlideData 校验滑动验证码
func CheckSlideData(point []int64, key string) bool {
if point == nil || key == "" {
return false
}
cacheDataByte, err := redis.Get(constant.CommentSubmitCaptchaRedisKey + key).Bytes()
if len(cacheDataByte) == 0 || err != nil {
return false
}
var dct *slide.Block
if err = json.Unmarshal(cacheDataByte, &dct); err != nil {
return false
}
chkRet := false
if 2 == len(point) {
sx, _ := strconv.ParseFloat(fmt.Sprintf("%v", point[0]), 64)
sy, _ := strconv.ParseFloat(fmt.Sprintf("%v", point[1]), 64)
chkRet = slide.CheckPoint(int64(sx), int64(sy), int64(dct.X), int64(dct.Y), 4)
}
if chkRet {
return true
}
return false
}
// CheckRotateData 校验旋转验证码
func CheckRotateData(angle string, key string) bool {
if angle == "" || key == "" {
return false
}
cacheDataByte, err := redis.Get(constant.UserLoginCaptchaRedisKey + key).Bytes()
if err != nil || len(cacheDataByte) == 0 {
global.LOG.Error(err)
return false
}
var dct *rotate.Block
if err = json.Unmarshal(cacheDataByte, &dct); err != nil {
global.LOG.Error(err)
return false
}
sAngle, err := strconv.ParseFloat(fmt.Sprintf("%v", angle), 64)
if err != nil {
global.LOG.Error(err)
return false
}
chkRet := rotate.CheckAngle(int64(sAngle), int64(dct.Angle), 2)
if chkRet {
return true
}
return false
}

View File

@@ -1,20 +1,25 @@
package utils package utils
import ( import (
"encoding/gob"
"encoding/json" "encoding/json"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"schisandra-cloud-album/api/user_api/dto"
"schisandra-cloud-album/global" "schisandra-cloud-album/global"
) )
// SetSession sets session data with key and data
func SetSession(c *gin.Context, key string, data interface{}) error { func SetSession(c *gin.Context, key string, data interface{}) error {
session, err := global.Session.Get(c.Request, key) session, err := global.Session.Get(c.Request, key)
if err != nil { if err != nil {
global.LOG.Error("SetSession failed: ", err) global.LOG.Error("SetSession failed: ", err)
return err return err
} }
gob.Register(data) jsonData, err := json.Marshal(data)
session.Values[key] = data if err != nil {
global.LOG.Error("SetSession failed: ", err)
return err
}
session.Values[key] = jsonData
err = session.Save(c.Request, c.Writer) err = session.Save(c.Request, c.Writer)
if err != nil { if err != nil {
global.LOG.Error("SetSession failed: ", err) global.LOG.Error("SetSession failed: ", err)
@@ -23,26 +28,28 @@ func SetSession(c *gin.Context, key string, data interface{}) error {
return nil return nil
} }
func GetSession(c *gin.Context, key string) interface{} { // GetSession gets session data with key
func GetSession(c *gin.Context, key string) dto.ResponseData {
session, err := global.Session.Get(c.Request, key) session, err := global.Session.Get(c.Request, key)
if err != nil { if err != nil {
global.LOG.Error("GetSession failed: ", err) global.LOG.Error("GetSession failed: ", err)
return nil return dto.ResponseData{}
} }
jsonData, ok := session.Values[key] jsonData, ok := session.Values[key]
if !ok { if !ok {
global.LOG.Error("GetSession failed: ", "key not found") global.LOG.Error("GetSession failed: ", "key not found")
return nil return dto.ResponseData{}
} }
var data interface{} var data dto.ResponseData
err = json.Unmarshal(jsonData.([]byte), &data) err = json.Unmarshal(jsonData.([]byte), &data)
if err != nil { if err != nil {
global.LOG.Error("GetSession failed: ", err) global.LOG.Error("GetSession failed: ", err)
return nil return dto.ResponseData{}
} }
return data return data
} }
// DelSession deletes session data with key
func DelSession(c *gin.Context, key string) { func DelSession(c *gin.Context, key string) {
session, err := global.Session.Get(c.Request, key) session, err := global.Session.Get(c.Request, key)
if err != nil { if err != nil {