feat: add geetest captcha (#953)

This commit is contained in:
Resulte Lee 2022-08-04 20:55:04 +08:00 committed by GitHub
parent d55ae7d1d2
commit 4ea482223d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 130 additions and 3 deletions

82
captcha/geetest.go Normal file
View File

@ -0,0 +1,82 @@
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package captcha
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"time"
"github.com/casdoor/casdoor/util"
)
const GEETESTCaptchaVerifyUrl = "http://gcaptcha4.geetest.com/validate"
type GEETESTCaptchaProvider struct {
}
func NewGEETESTCaptchaProvider() *GEETESTCaptchaProvider {
captcha := &GEETESTCaptchaProvider{}
return captcha
}
func (captcha *GEETESTCaptchaProvider) VerifyCaptcha(token, clientSecret string) (bool, error) {
pathData, err := url.ParseQuery(token)
if err != nil {
return false, err
}
signToken := util.GetHmacSha256(clientSecret, pathData["lot_number"][0])
formData := make(url.Values)
formData["lot_number"] = []string{pathData["lot_number"][0]}
formData["captcha_output"] = []string{pathData["captcha_output"][0]}
formData["pass_token"] = []string{pathData["pass_token"][0]}
formData["gen_time"] = []string{pathData["gen_time"][0]}
formData["sign_token"] = []string{signToken}
captchaId := pathData["captcha_id"][0]
cli := http.Client{Timeout: time.Second * 5}
resp, err := cli.PostForm(fmt.Sprintf("%s?captcha_id=%s", GEETESTCaptchaVerifyUrl, captchaId), formData)
if err != nil || resp.StatusCode != 200 {
return false, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return false, err
}
type captchaResponse struct {
Result string `json:"result"`
Reason string `json:"reason"`
}
captchaResp := &captchaResponse{}
err = json.Unmarshal(body, captchaResp)
if err != nil {
return false, err
}
if captchaResp.Result == "success" {
return true, nil
}
return false, errors.New(captchaResp.Reason)
}

View File

@ -27,6 +27,8 @@ func GetCaptchaProvider(captchaType string) CaptchaProvider {
return NewHCaptchaProvider()
} else if captchaType == "Aliyun Captcha" {
return NewAliyunCaptchaProvider()
} else if captchaType == "GEETEST" {
return NewGEETESTCaptchaProvider()
}
return nil
}

View File

@ -17,7 +17,9 @@ package util
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
)
func GetHmacSha1(keyStr, value string) string {
@ -28,3 +30,10 @@ func GetHmacSha1(keyStr, value string) string {
return res
}
func GetHmacSha256(key string, data string) string {
mac := hmac.New(sha256.New, []byte(key))
mac.Write([]byte(data))
return hex.EncodeToString(mac.Sum(nil))
}

View File

@ -122,6 +122,10 @@ export const OtherProviderInfo = {
"Aliyun Captcha": {
logo: `${StaticBaseUrl}/img/social_aliyun.png`,
url: "https://help.aliyun.com/product/28308.html",
},
"GEETEST": {
logo: `${StaticBaseUrl}/img/social_geetest.png`,
url: "https://www.geetest.com",
}
}
};
@ -615,6 +619,7 @@ export function getProviderTypeOptions(category) {
{id: "reCAPTCHA", name: "reCAPTCHA"},
{id: "hCaptcha", name: "hCaptcha"},
{id: "Aliyun Captcha", name: "Aliyun Captcha"},
{id: "GEETEST", name: "GEETEST"},
]);
} else {
return [];

View File

@ -25,7 +25,7 @@ export const CaptchaWidget = ({captchaType, subType, siteKey, clientSecret, onCh
useEffect(() => {
switch (captchaType) {
case "reCAPTCHA":
case "reCAPTCHA": {
const reTimer = setInterval(() => {
if (!window.grecaptcha) {
loadScript("https://recaptcha.net/recaptcha/api.js");
@ -39,7 +39,8 @@ export const CaptchaWidget = ({captchaType, subType, siteKey, clientSecret, onCh
}
}, 300);
break;
case "hCaptcha":
}
case "hCaptcha": {
const hTimer = setInterval(() => {
if (!window.hcaptcha) {
loadScript("https://js.hcaptcha.com/1/api.js");
@ -53,7 +54,8 @@ export const CaptchaWidget = ({captchaType, subType, siteKey, clientSecret, onCh
}
}, 300);
break;
case "Aliyun Captcha":
}
case "Aliyun Captcha": {
const AWSCTimer = setInterval(() => {
if (!window.AWSC) {
loadScript("https://g.alicdn.com/AWSC/AWSC/awsc.js");
@ -76,6 +78,33 @@ export const CaptchaWidget = ({captchaType, subType, siteKey, clientSecret, onCh
}
}, 300);
break;
}
case "GEETEST": {
let getLock = false;
const gTimer = setInterval(() => {
if (!window.initGeetest4) {
loadScript("https://static.geetest.com/v4/gt4.js");
}
if (window.initGeetest4 && siteKey && !getLock) {
const captchaId = String(siteKey);
window.initGeetest4({
captchaId,
product: "float",
}, function(captchaObj) {
if (!getLock) {
captchaObj.appendTo("#captcha");
getLock = true;
}
captchaObj.onSuccess(function() {
const result = captchaObj.getValidate();
onChange(`lot_number=${result.lot_number}&captcha_output=${result.captcha_output}&pass_token=${result.pass_token}&gen_time=${result.gen_time}&captcha_id=${siteKey}`);
});
});
clearInterval(gTimer);
}
}, 500);
break;
}
default:
break;
}