You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.8 KiB
128 lines
3.8 KiB
package middleware
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
model "github.com/cloudreve/Cloudreve/v3/models"
|
|
"github.com/cloudreve/Cloudreve/v3/pkg/recaptcha"
|
|
"github.com/cloudreve/Cloudreve/v3/pkg/serializer"
|
|
"github.com/cloudreve/Cloudreve/v3/pkg/util"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/mojocn/base64Captcha"
|
|
captcha "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/captcha/v20190722"
|
|
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
|
|
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
|
|
"io"
|
|
"io/ioutil"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type req struct {
|
|
CaptchaCode string `json:"captchaCode"`
|
|
Ticket string `json:"ticket"`
|
|
Randstr string `json:"randstr"`
|
|
}
|
|
|
|
const (
|
|
captchaNotMatch = "CAPTCHA not match."
|
|
captchaRefresh = "Verification failed, please refresh the page and retry."
|
|
)
|
|
|
|
// CaptchaRequired 验证请求签名
|
|
func CaptchaRequired(configName string) gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
// 相关设定
|
|
options := model.GetSettingByNames(configName,
|
|
"captcha_type",
|
|
"captcha_ReCaptchaSecret",
|
|
"captcha_TCaptcha_SecretId",
|
|
"captcha_TCaptcha_SecretKey",
|
|
"captcha_TCaptcha_CaptchaAppId",
|
|
"captcha_TCaptcha_AppSecretKey")
|
|
// 检查验证码
|
|
isCaptchaRequired := model.IsTrueVal(options[configName])
|
|
|
|
if isCaptchaRequired {
|
|
var service req
|
|
bodyCopy := new(bytes.Buffer)
|
|
_, err := io.Copy(bodyCopy, c.Request.Body)
|
|
if err != nil {
|
|
c.JSON(200, serializer.Err(serializer.CodeCaptchaError, captchaNotMatch, err))
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
bodyData := bodyCopy.Bytes()
|
|
err = json.Unmarshal(bodyData, &service)
|
|
if err != nil {
|
|
c.JSON(200, serializer.Err(serializer.CodeCaptchaError, captchaNotMatch, err))
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
c.Request.Body = ioutil.NopCloser(bytes.NewReader(bodyData))
|
|
switch options["captcha_type"] {
|
|
case "normal":
|
|
captchaID := util.GetSession(c, "captchaID")
|
|
util.DeleteSession(c, "captchaID")
|
|
if captchaID == nil || !base64Captcha.VerifyCaptcha(captchaID.(string), service.CaptchaCode) {
|
|
c.JSON(200, serializer.Err(serializer.CodeCaptchaError, captchaNotMatch, err))
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
break
|
|
case "recaptcha":
|
|
reCAPTCHA, err := recaptcha.NewReCAPTCHA(options["captcha_ReCaptchaSecret"], recaptcha.V2, 10*time.Second)
|
|
if err != nil {
|
|
util.Log().Warning("reCAPTCHA verification failed, %s", err)
|
|
c.Abort()
|
|
break
|
|
}
|
|
|
|
err = reCAPTCHA.Verify(service.CaptchaCode)
|
|
if err != nil {
|
|
util.Log().Warning("reCAPTCHA verification failed, %s", err)
|
|
c.JSON(200, serializer.Err(serializer.CodeCaptchaRefreshNeeded, captchaRefresh, nil))
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
break
|
|
case "tcaptcha":
|
|
credential := common.NewCredential(
|
|
options["captcha_TCaptcha_SecretId"],
|
|
options["captcha_TCaptcha_SecretKey"],
|
|
)
|
|
cpf := profile.NewClientProfile()
|
|
cpf.HttpProfile.Endpoint = "captcha.tencentcloudapi.com"
|
|
client, _ := captcha.NewClient(credential, "", cpf)
|
|
request := captcha.NewDescribeCaptchaResultRequest()
|
|
request.CaptchaType = common.Uint64Ptr(9)
|
|
appid, _ := strconv.Atoi(options["captcha_TCaptcha_CaptchaAppId"])
|
|
request.CaptchaAppId = common.Uint64Ptr(uint64(appid))
|
|
request.AppSecretKey = common.StringPtr(options["captcha_TCaptcha_AppSecretKey"])
|
|
request.Ticket = common.StringPtr(service.Ticket)
|
|
request.Randstr = common.StringPtr(service.Randstr)
|
|
request.UserIp = common.StringPtr(c.ClientIP())
|
|
response, err := client.DescribeCaptchaResult(request)
|
|
if err != nil {
|
|
util.Log().Warning("TCaptcha verification failed, %s", err)
|
|
c.Abort()
|
|
break
|
|
}
|
|
|
|
if *response.Response.CaptchaCode != int64(1) {
|
|
c.JSON(200, serializer.Err(serializer.CodeCaptchaRefreshNeeded, captchaRefresh, nil))
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
break
|
|
}
|
|
}
|
|
c.Next()
|
|
}
|
|
}
|