Files
AntiCaptcha/internal/handler/captcha.go
T
admin a6b03a6152
Build and Deploy / build (push) Failing after 1m49s
Build and Deploy / deploy (push) Has been skipped
fix: 安装时创建管理员用户,登录从数据库验证
2026-07-16 18:50:54 +00:00

334 lines
8.9 KiB
Go

package handler
import (
"net/http"
"anticaptcha/internal/captcha"
"anticaptcha/internal/database"
"anticaptcha/internal/middleware"
"anticaptcha/internal/model"
"github.com/gin-gonic/gin"
)
type CaptchaHandler struct {
handler *captcha.Handler
}
func NewCaptchaHandler(h *captcha.Handler) *CaptchaHandler {
return &CaptchaHandler{handler: h}
}
func (h *CaptchaHandler) RegisterRoutes(r *gin.RouterGroup, authRequired bool) {
captcha := r.Group("/api")
// 公共接口
captcha.POST("/register", h.Register)
captcha.POST("/login", h.Login)
captcha.GET("/tokens/verification", middleware.JWTAuth(), h.VerifyToken)
// 需要认证的接口
auth := captcha.Group("")
if authRequired {
auth.Use(middleware.JWTAuth())
}
// 验证码识别接口
auth.POST("/ocr", h.OCR)
auth.POST("/math", h.Math)
auth.POST("/slider/match", h.SliderMatch)
auth.POST("/slider/comparison", h.SliderComparison)
auth.POST("/compare/similarity", h.CompareSimilarity)
auth.POST("/rotate/single/rotate", h.SingleRotate)
auth.POST("/rotate/double/rotate", h.DoubleRotate)
auth.POST("/detection/icon", h.DetectionIcon)
auth.POST("/detection/text", h.DetectionText)
auth.POST("/detection/icon/order", h.DetectionIconOrder)
auth.POST("/detection/text/order", h.DetectionTextOrder)
// 管理接口
admin := captcha.Group("/admin")
admin.Use(middleware.JWTAuth(), middleware.AdminOnly())
admin.POST("/generate_code", h.GenerateCode)
admin.GET("/regcodes", h.GetRegCodes)
admin.DELETE("/regcodes/:id", h.DeleteRegCode)
admin.GET("/users", h.GetUsers)
admin.PUT("/users/:username", h.UpdateUser)
admin.GET("/costs", h.GetEndpointCosts)
admin.POST("/costs", h.SetEndpointCost)
}
// 注册
func (h *CaptchaHandler) Register(c *gin.Context) {
var req struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
RegistrationCode string `json:"registration_code" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// TODO: 实现注册逻辑
c.JSON(http.StatusOK, gin.H{"message": "注册成功"})
}
// 登录
func (h *CaptchaHandler) Login(c *gin.Context) {
var req struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 从数据库验证用户
user, err := database.ValidateUser(req.Username, req.Password)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
return
}
token, err := middleware.GenerateToken(int(user.ID), user.Username, string(user.Role))
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "生成令牌失败"})
return
}
c.JSON(http.StatusOK, model.LoginResponse{
AccessToken: token,
TokenType: "bearer",
Role: string(user.Role),
Balance: user.Balance,
})
}
// 验证令牌
func (h *CaptchaHandler) VerifyToken(c *gin.Context) {
userID := middleware.GetCurrentUserID(c)
c.JSON(http.StatusOK, gin.H{
"user_id": userID,
"valid": true,
})
}
// OCR 识别
func (h *CaptchaHandler) OCR(c *gin.Context) {
var req model.OCRRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := h.handler.OCR(req.ImageBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: result})
}
// 数学计算
func (h *CaptchaHandler) Math(c *gin.Context) {
var req model.MathRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := h.handler.Math(req.ImageBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: result})
}
// 滑块匹配
func (h *CaptchaHandler) SliderMatch(c *gin.Context) {
var req model.SliderMatchRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
x, err := h.handler.SliderMatch(req.TargetBase64, req.BackgroundBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: x})
}
// 阴影滑块
func (h *CaptchaHandler) SliderComparison(c *gin.Context) {
var req model.SliderMatchRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
x, err := h.handler.SliderComparison(req.TargetBase64, req.BackgroundBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: x})
}
// 图片相似度
func (h *CaptchaHandler) CompareSimilarity(c *gin.Context) {
var req model.CompareImageRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
similarity, err := h.handler.CompareSimilarity(req.Image1Base64, req.Image2Base64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: similarity})
}
// 单图旋转
func (h *CaptchaHandler) SingleRotate(c *gin.Context) {
var req model.RotateRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
angle, err := h.handler.SingleRotate(req.ImageBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: angle})
}
// 双图旋转
func (h *CaptchaHandler) DoubleRotate(c *gin.Context) {
var req model.DoubleRotateRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
angle, err := h.handler.DoubleRotate(req.InsideBase64, req.OutsideBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: angle})
}
// 图标检测
func (h *CaptchaHandler) DetectionIcon(c *gin.Context) {
var req model.DetectIconRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := h.handler.DetectionIcon(req.ImageBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: result})
}
// 文字检测
func (h *CaptchaHandler) DetectionText(c *gin.Context) {
var req model.DetectIconRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := h.handler.DetectionText(req.ImageBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: result})
}
// 按序图标检测
func (h *CaptchaHandler) DetectionIconOrder(c *gin.Context) {
var req model.DetectIconOrderRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := h.handler.DetectionIconOrder(req.OrderImgBase64, req.TargetImgBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: result})
}
// 按序文字检测
func (h *CaptchaHandler) DetectionTextOrder(c *gin.Context) {
var req model.DetectIconOrderRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
result, err := h.handler.DetectionTextOrder(req.OrderImgBase64, req.TargetImgBase64)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.CaptchaResult{Result: result})
}
// 管理接口占位
func (h *CaptchaHandler) GenerateCode(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": "placeholder"})
}
func (h *CaptchaHandler) GetRegCodes(c *gin.Context) {
c.JSON(http.StatusOK, []interface{}{})
}
func (h *CaptchaHandler) DeleteRegCode(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "删除成功"})
}
func (h *CaptchaHandler) GetUsers(c *gin.Context) {
c.JSON(http.StatusOK, []interface{}{})
}
func (h *CaptchaHandler) UpdateUser(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "更新成功"})
}
func (h *CaptchaHandler) GetEndpointCosts(c *gin.Context) {
c.JSON(http.StatusOK, []interface{}{})
}
func (h *CaptchaHandler) SetEndpointCost(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "设置成功"})
}