mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-01 18:40:18 +08:00
feat: upgrade Alibaba cloud captcha provider from v1 to v2 (#3879)
This commit is contained in:
@ -15,32 +15,51 @@
|
|||||||
package captcha
|
package captcha
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
|
||||||
"errors"
|
openapiutil "github.com/alibabacloud-go/openapi-util/service"
|
||||||
"fmt"
|
teaUtil "github.com/alibabacloud-go/tea-utils/v2/service"
|
||||||
"io"
|
"github.com/alibabacloud-go/tea/tea"
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const AliyunCaptchaVerifyUrl = "http://afs.aliyuncs.com"
|
const AliyunCaptchaVerifyUrl = "captcha.cn-shanghai.aliyuncs.com"
|
||||||
|
|
||||||
type captchaSuccessResponse struct {
|
type VerifyCaptchaRequest struct {
|
||||||
Code int `json:"Code"`
|
CaptchaVerifyParam *string `json:"CaptchaVerifyParam,omitempty" xml:"CaptchaVerifyParam,omitempty"`
|
||||||
Msg string `json:"Msg"`
|
SceneId *string `json:"SceneId,omitempty" xml:"SceneId,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type captchaFailResponse struct {
|
type VerifyCaptchaResponseBodyResult struct {
|
||||||
Code string `json:"Code"`
|
VerifyResult *bool `json:"VerifyResult,omitempty" xml:"VerifyResult,omitempty"`
|
||||||
Message string `json:"Message"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type VerifyCaptchaResponseBody struct {
|
||||||
|
Code *string `json:"Code,omitempty" xml:"Code,omitempty"`
|
||||||
|
Message *string `json:"Message,omitempty" xml:"Message,omitempty"`
|
||||||
|
// Id of the request
|
||||||
|
RequestId *string `json:"RequestId,omitempty" xml:"RequestId,omitempty"`
|
||||||
|
Result *VerifyCaptchaResponseBodyResult `json:"Result,omitempty" xml:"Result,omitempty" type:"Struct"`
|
||||||
|
Success *bool `json:"Success,omitempty" xml:"Success,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifyIntelligentCaptchaResponseBodyResult struct {
|
||||||
|
VerifyCode *string `json:"VerifyCode,omitempty" xml:"VerifyCode,omitempty"`
|
||||||
|
VerifyResult *bool `json:"VerifyResult,omitempty" xml:"VerifyResult,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifyIntelligentCaptchaResponseBody struct {
|
||||||
|
Code *string `json:"Code,omitempty" xml:"Code,omitempty"`
|
||||||
|
Message *string `json:"Message,omitempty" xml:"Message,omitempty"`
|
||||||
|
// Id of the request
|
||||||
|
RequestId *string `json:"RequestId,omitempty" xml:"RequestId,omitempty"`
|
||||||
|
Result *VerifyIntelligentCaptchaResponseBodyResult `json:"Result,omitempty" xml:"Result,omitempty" type:"Struct"`
|
||||||
|
Success *bool `json:"Success,omitempty" xml:"Success,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifyIntelligentCaptchaResponse struct {
|
||||||
|
Headers map[string]*string `json:"headers,omitempty" xml:"headers,omitempty" require:"true"`
|
||||||
|
StatusCode *int32 `json:"statusCode,omitempty" xml:"statusCode,omitempty" require:"true"`
|
||||||
|
Body *VerifyIntelligentCaptchaResponseBody `json:"body,omitempty" xml:"body,omitempty" require:"true"`
|
||||||
|
}
|
||||||
type AliyunCaptchaProvider struct{}
|
type AliyunCaptchaProvider struct{}
|
||||||
|
|
||||||
func NewAliyunCaptchaProvider() *AliyunCaptchaProvider {
|
func NewAliyunCaptchaProvider() *AliyunCaptchaProvider {
|
||||||
@ -48,68 +67,69 @@ func NewAliyunCaptchaProvider() *AliyunCaptchaProvider {
|
|||||||
return captcha
|
return captcha
|
||||||
}
|
}
|
||||||
|
|
||||||
func contentEscape(str string) string {
|
func (captcha *AliyunCaptchaProvider) VerifyCaptcha(token, clientId, clientSecret, clientId2 string) (bool, error) {
|
||||||
str = strings.Replace(str, " ", "%20", -1)
|
config := &openapi.Config{}
|
||||||
str = url.QueryEscape(str)
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
func (captcha *AliyunCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
config.Endpoint = tea.String(AliyunCaptchaVerifyUrl)
|
||||||
pathData, err := url.ParseQuery(token)
|
config.ConnectTimeout = tea.Int(5000)
|
||||||
|
config.ReadTimeout = tea.Int(5000)
|
||||||
|
config.AccessKeyId = tea.String(clientId)
|
||||||
|
config.AccessKeySecret = tea.String(clientSecret)
|
||||||
|
|
||||||
|
client := new(openapi.Client)
|
||||||
|
err := client.Init(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pathData["Action"] = []string{"AuthenticateSig"}
|
request := VerifyCaptchaRequest{CaptchaVerifyParam: tea.String(token), SceneId: tea.String(clientId2)}
|
||||||
pathData["Format"] = []string{"json"}
|
|
||||||
pathData["SignatureMethod"] = []string{"HMAC-SHA1"}
|
|
||||||
pathData["SignatureNonce"] = []string{strconv.FormatInt(time.Now().UnixNano(), 10)}
|
|
||||||
pathData["SignatureVersion"] = []string{"1.0"}
|
|
||||||
pathData["Timestamp"] = []string{time.Now().UTC().Format("2006-01-02T15:04:05Z")}
|
|
||||||
pathData["Version"] = []string{"2018-01-12"}
|
|
||||||
|
|
||||||
var keys []string
|
err = teaUtil.ValidateModel(&request)
|
||||||
for k := range pathData {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
sort.Strings(keys)
|
|
||||||
|
|
||||||
sortQuery := ""
|
|
||||||
for _, k := range keys {
|
|
||||||
sortQuery += k + "=" + contentEscape(pathData[k][0]) + "&"
|
|
||||||
}
|
|
||||||
sortQuery = strings.TrimSuffix(sortQuery, "&")
|
|
||||||
|
|
||||||
stringToSign := fmt.Sprintf("GET&%s&%s", url.QueryEscape("/"), url.QueryEscape(sortQuery))
|
|
||||||
|
|
||||||
signature := util.GetHmacSha1(clientSecret+"&", stringToSign)
|
|
||||||
|
|
||||||
resp, err := http.Get(fmt.Sprintf("%s?%s&Signature=%s", AliyunCaptchaVerifyUrl, sortQuery, url.QueryEscape(signature)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
runtime := &teaUtil.RuntimeOptions{}
|
||||||
body, err := io.ReadAll(resp.Body)
|
|
||||||
|
body := map[string]interface{}{}
|
||||||
|
if !tea.BoolValue(teaUtil.IsUnset(request.CaptchaVerifyParam)) {
|
||||||
|
body["CaptchaVerifyParam"] = request.CaptchaVerifyParam
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tea.BoolValue(teaUtil.IsUnset(request.SceneId)) {
|
||||||
|
body["SceneId"] = request.SceneId
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &openapi.OpenApiRequest{
|
||||||
|
Body: openapiutil.ParseToMap(body),
|
||||||
|
}
|
||||||
|
params := &openapi.Params{
|
||||||
|
Action: tea.String("VerifyIntelligentCaptcha"),
|
||||||
|
Version: tea.String("2023-03-05"),
|
||||||
|
Protocol: tea.String("HTTPS"),
|
||||||
|
Pathname: tea.String("/"),
|
||||||
|
Method: tea.String("POST"),
|
||||||
|
AuthType: tea.String("AK"),
|
||||||
|
Style: tea.String("RPC"),
|
||||||
|
ReqBodyType: tea.String("formData"),
|
||||||
|
BodyType: tea.String("json"),
|
||||||
|
}
|
||||||
|
|
||||||
|
res := &VerifyIntelligentCaptchaResponse{}
|
||||||
|
|
||||||
|
resBody, err := client.CallApi(params, req, runtime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleCaptchaResponse(body)
|
err = tea.Convert(resBody, &res)
|
||||||
}
|
|
||||||
|
|
||||||
func handleCaptchaResponse(body []byte) (bool, error) {
|
|
||||||
captchaResp := &captchaSuccessResponse{}
|
|
||||||
err := json.Unmarshal(body, captchaResp)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
captchaFailResp := &captchaFailResponse{}
|
return false, err
|
||||||
err = json.Unmarshal(body, captchaFailResp)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, errors.New(captchaFailResp.Message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
if res.Body.Result.VerifyResult != nil && *res.Body.Result.VerifyResult {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,6 @@ func NewDefaultCaptchaProvider() *DefaultCaptchaProvider {
|
|||||||
return captcha
|
return captcha
|
||||||
}
|
}
|
||||||
|
|
||||||
func (captcha *DefaultCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
func (captcha *DefaultCaptchaProvider) VerifyCaptcha(token, clientId, clientSecret, clientId2 string) (bool, error) {
|
||||||
return object.VerifyCaptcha(clientSecret, token), nil
|
return object.VerifyCaptcha(clientSecret, token), nil
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ func NewGEETESTCaptchaProvider() *GEETESTCaptchaProvider {
|
|||||||
return captcha
|
return captcha
|
||||||
}
|
}
|
||||||
|
|
||||||
func (captcha *GEETESTCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
func (captcha *GEETESTCaptchaProvider) VerifyCaptcha(token, clientId, clientSecret, clientId2 string) (bool, error) {
|
||||||
pathData, err := url.ParseQuery(token)
|
pathData, err := url.ParseQuery(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
@ -32,7 +32,7 @@ func NewHCaptchaProvider() *HCaptchaProvider {
|
|||||||
return captcha
|
return captcha
|
||||||
}
|
}
|
||||||
|
|
||||||
func (captcha *HCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
func (captcha *HCaptchaProvider) VerifyCaptcha(token, clientId, clientSecret, clientId2 string) (bool, error) {
|
||||||
reqData := url.Values{
|
reqData := url.Values{
|
||||||
"secret": {clientSecret},
|
"secret": {clientSecret},
|
||||||
"response": {token},
|
"response": {token},
|
||||||
|
@ -17,7 +17,7 @@ package captcha
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type CaptchaProvider interface {
|
type CaptchaProvider interface {
|
||||||
VerifyCaptcha(token, clientSecret string) (bool, error)
|
VerifyCaptcha(token, clientId, clientSecret, clientId2 string) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
||||||
@ -43,11 +43,11 @@ func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyCaptchaByCaptchaType(captchaType, token, clientSecret string) (bool, error) {
|
func VerifyCaptchaByCaptchaType(captchaType, token, clientId, clientSecret, clientId2 string) (bool, error) {
|
||||||
provider := GetCaptchaProvider(captchaType)
|
provider := GetCaptchaProvider(captchaType)
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
return false, fmt.Errorf("invalid captcha provider: %s", captchaType)
|
return false, fmt.Errorf("invalid captcha provider: %s", captchaType)
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider.VerifyCaptcha(token, clientSecret)
|
return provider.VerifyCaptcha(token, clientId, clientSecret, clientId2)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func NewReCaptchaProvider() *ReCaptchaProvider {
|
|||||||
return captcha
|
return captcha
|
||||||
}
|
}
|
||||||
|
|
||||||
func (captcha *ReCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
func (captcha *ReCaptchaProvider) VerifyCaptcha(token, clientId, clientSecret, clientId2 string) (bool, error) {
|
||||||
reqData := url.Values{
|
reqData := url.Values{
|
||||||
"secret": {clientSecret},
|
"secret": {clientSecret},
|
||||||
"response": {token},
|
"response": {token},
|
||||||
|
@ -32,7 +32,7 @@ func NewCloudflareTurnstileProvider() *CloudflareTurnstileProvider {
|
|||||||
return captcha
|
return captcha
|
||||||
}
|
}
|
||||||
|
|
||||||
func (captcha *CloudflareTurnstileProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
|
func (captcha *CloudflareTurnstileProvider) VerifyCaptcha(token, clientId, clientSecret, clientId2 string) (bool, error) {
|
||||||
reqData := url.Values{
|
reqData := url.Values{
|
||||||
"secret": {clientSecret},
|
"secret": {clientSecret},
|
||||||
"response": {token},
|
"response": {token},
|
||||||
|
@ -571,7 +571,7 @@ func (c *ApiController) Login() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isHuman bool
|
var isHuman bool
|
||||||
isHuman, err = captcha.VerifyCaptchaByCaptchaType(authForm.CaptchaType, authForm.CaptchaToken, authForm.ClientSecret)
|
isHuman, err = captcha.VerifyCaptchaByCaptchaType(authForm.CaptchaType, authForm.CaptchaToken, captchaProvider.ClientId, authForm.ClientSecret, captchaProvider.ClientId2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
@ -160,7 +160,7 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
if captchaProvider := captcha.GetCaptchaProvider(vform.CaptchaType); captchaProvider == nil {
|
if captchaProvider := captcha.GetCaptchaProvider(vform.CaptchaType); captchaProvider == nil {
|
||||||
c.ResponseError(c.T("general:don't support captchaProvider: ") + vform.CaptchaType)
|
c.ResponseError(c.T("general:don't support captchaProvider: ") + vform.CaptchaType)
|
||||||
return
|
return
|
||||||
} else if isHuman, err := captchaProvider.VerifyCaptcha(vform.CaptchaToken, vform.ClientSecret); err != nil {
|
} else if isHuman, err := captchaProvider.VerifyCaptcha(vform.CaptchaToken, provider.ClientId, vform.ClientSecret, provider.ClientId2); err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
} else if !isHuman {
|
} else if !isHuman {
|
||||||
@ -349,7 +349,7 @@ func (c *ApiController) VerifyCaptcha() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid, err := provider.VerifyCaptcha(vform.CaptchaToken, vform.ClientSecret)
|
isValid, err := provider.VerifyCaptcha(vform.CaptchaToken, captchaProvider.ClientId, vform.ClientSecret, captchaProvider.ClientId2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
|
2
go.mod
2
go.mod
@ -7,6 +7,7 @@ require (
|
|||||||
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
|
||||||
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4
|
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4
|
||||||
github.com/alibabacloud-go/facebody-20191230/v5 v5.1.2
|
github.com/alibabacloud-go/facebody-20191230/v5 v5.1.2
|
||||||
|
github.com/alibabacloud-go/openapi-util v0.1.0
|
||||||
github.com/alibabacloud-go/tea v1.3.2
|
github.com/alibabacloud-go/tea v1.3.2
|
||||||
github.com/alibabacloud-go/tea-utils/v2 v2.0.7
|
github.com/alibabacloud-go/tea-utils/v2 v2.0.7
|
||||||
github.com/aws/aws-sdk-go v1.45.5
|
github.com/aws/aws-sdk-go v1.45.5
|
||||||
@ -90,7 +91,6 @@ require (
|
|||||||
github.com/alibabacloud-go/darabonba-number v1.0.4 // indirect
|
github.com/alibabacloud-go/darabonba-number v1.0.4 // indirect
|
||||||
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
github.com/alibabacloud-go/debug v1.0.1 // indirect
|
||||||
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
|
||||||
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
|
|
||||||
github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 // indirect
|
github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 // indirect
|
||||||
github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect
|
github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect
|
||||||
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect
|
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect
|
||||||
|
@ -371,11 +371,6 @@ class ProviderEditPage extends React.Component {
|
|||||||
{id: "Third-party", name: i18next.t("provider:Third-party")},
|
{id: "Third-party", name: i18next.t("provider:Third-party")},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
} else if (type === "Aliyun Captcha") {
|
|
||||||
return [
|
|
||||||
{id: "nc", name: i18next.t("provider:Sliding Validation")},
|
|
||||||
{id: "ic", name: i18next.t("provider:Intelligent Validation")},
|
|
||||||
];
|
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -674,7 +669,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
{
|
{
|
||||||
this.state.provider.type !== "WeCom" && this.state.provider.type !== "Infoflow" && this.state.provider.type !== "Aliyun Captcha" ? null : (
|
this.state.provider.type !== "WeCom" && this.state.provider.type !== "Infoflow" ? null : (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={2}>
|
<Col style={{marginTop: "5px"}} span={2}>
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React, {useEffect} from "react";
|
import React, {useEffect} from "react";
|
||||||
|
import {Button} from "antd";
|
||||||
|
import i18next from "i18next";
|
||||||
|
|
||||||
export const CaptchaWidget = (props) => {
|
export const CaptchaWidget = (props) => {
|
||||||
const {captchaType, subType, siteKey, clientSecret, clientId2, clientSecret2, onChange} = props;
|
const {captchaType, subType, siteKey, clientSecret, clientId2, clientSecret2, onChange} = props;
|
||||||
@ -85,23 +87,34 @@ export const CaptchaWidget = (props) => {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Aliyun Captcha": {
|
case "Aliyun Captcha": {
|
||||||
|
window.AliyunCaptchaConfig = {
|
||||||
|
region: "cn",
|
||||||
|
prefix: clientSecret2,
|
||||||
|
};
|
||||||
|
|
||||||
const AWSCTimer = setInterval(() => {
|
const AWSCTimer = setInterval(() => {
|
||||||
if (!window.AWSC) {
|
if (!window.initAliyunCaptcha) {
|
||||||
loadScript("https://g.alicdn.com/AWSC/AWSC/awsc.js");
|
loadScript("https://o.alicdn.com/captcha-frontend/aliyunCaptcha/AliyunCaptcha.js");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.AWSC) {
|
if (window.initAliyunCaptcha) {
|
||||||
if (clientSecret2 && clientSecret2 !== "***") {
|
if (clientSecret2 && clientSecret2 !== "***") {
|
||||||
window.AWSC.use(subType, function(state, module) {
|
window.initAliyunCaptcha({
|
||||||
module.init({
|
SceneId: clientId2,
|
||||||
appkey: clientSecret2,
|
mode: "embed",
|
||||||
scene: clientId2,
|
element: "#captcha",
|
||||||
renderTo: "captcha",
|
button: "#captcha-button",
|
||||||
success: function(data) {
|
captchaVerifyCallback: (data) => {
|
||||||
onChange(`SessionId=${data.sessionId}&AccessKeyId=${siteKey}&Scene=${clientId2}&AppKey=${clientSecret2}&Token=${data.token}&Sig=${data.sig}&RemoteIp=192.168.0.1`);
|
onChange(data.toString());
|
||||||
},
|
},
|
||||||
});
|
slideStyle: {
|
||||||
|
width: 320,
|
||||||
|
height: 40,
|
||||||
|
},
|
||||||
|
language: "cn",
|
||||||
|
immediate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
clearInterval(AWSCTimer);
|
clearInterval(AWSCTimer);
|
||||||
}
|
}
|
||||||
@ -154,5 +167,9 @@ export const CaptchaWidget = (props) => {
|
|||||||
}
|
}
|
||||||
}, [captchaType, subType, siteKey, clientSecret, clientId2, clientSecret2]);
|
}, [captchaType, subType, siteKey, clientSecret, clientId2, clientSecret2]);
|
||||||
|
|
||||||
return <div id="captcha" />;
|
return <div id="captcha">
|
||||||
|
{
|
||||||
|
captchaType === "Aliyun Captcha" && window.initAliyunCaptcha ? <Button id="captcha-button">{i18next.t("general:Verifications")}</Button> : null
|
||||||
|
}
|
||||||
|
</div>;
|
||||||
};
|
};
|
||||||
|
@ -44,6 +44,12 @@ export const CaptchaModal = (props) => {
|
|||||||
}
|
}
|
||||||
}, [visible]);
|
}, [visible]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (captchaToken !== "" && captchaType !== "Default") {
|
||||||
|
handleOk();
|
||||||
|
}
|
||||||
|
}, [captchaToken]);
|
||||||
|
|
||||||
const handleOk = () => {
|
const handleOk = () => {
|
||||||
onOk?.(captchaType, captchaToken, clientSecret);
|
onOk?.(captchaType, captchaToken, clientSecret);
|
||||||
};
|
};
|
||||||
@ -138,19 +144,18 @@ export const CaptchaModal = (props) => {
|
|||||||
if (!regex.test(captchaToken)) {
|
if (!regex.test(captchaToken)) {
|
||||||
isOkDisabled = true;
|
isOkDisabled = true;
|
||||||
}
|
}
|
||||||
} else if (captchaToken === "") {
|
return [
|
||||||
isOkDisabled = true;
|
null,
|
||||||
|
<Button key="ok" disabled={isOkDisabled} type="primary" onClick={handleOk}>{i18next.t("general:OK")}</Button>,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return null;
|
||||||
<Button key="cancel" onClick={handleCancel}>{i18next.t("general:Cancel")}</Button>,
|
|
||||||
<Button key="ok" disabled={isOkDisabled} type="primary" onClick={handleOk}>{i18next.t("general:OK")}</Button>,
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
closable={false}
|
closable={true}
|
||||||
maskClosable={false}
|
maskClosable={false}
|
||||||
destroyOnClose={true}
|
destroyOnClose={true}
|
||||||
title={i18next.t("general:Captcha")}
|
title={i18next.t("general:Captcha")}
|
||||||
@ -160,6 +165,7 @@ export const CaptchaModal = (props) => {
|
|||||||
width={350}
|
width={350}
|
||||||
footer={renderFooter()}
|
footer={renderFooter()}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
|
afterClose={handleCancel}
|
||||||
onOk={handleOk}
|
onOk={handleOk}
|
||||||
>
|
>
|
||||||
<div style={{marginTop: "20px", marginBottom: "50px"}}>
|
<div style={{marginTop: "20px", marginBottom: "50px"}}>
|
||||||
|
Reference in New Issue
Block a user