mirror of
https://github.com/Rayzggz/server_torii.git
synced 2025-06-16 12:11:22 +08:00
feat: CAPTCHA SESSION
This commit is contained in:
@ -66,6 +66,11 @@
|
||||
+ "您未能通过人机验证,请刷新页面后重试。");
|
||||
window.location.reload();
|
||||
break;
|
||||
case "badSession":
|
||||
alert("Session invalid, please refresh the page and try again.\n"
|
||||
+ "会话无效,请刷新页面后重试。");
|
||||
window.location.reload();
|
||||
break;
|
||||
default:
|
||||
alert("Unexpected error occurred, please refresh the page and try again.\n"
|
||||
+ "发生了意料之外的错误,请刷新页面后重试。");
|
||||
|
@ -1,3 +1,4 @@
|
||||
secret_key: "0378b0f84c4310279918d71a5647ba5d"
|
||||
captcha_validate_time: 600
|
||||
captcha_challenge_session_timeout: 120
|
||||
hcaptcha_secret: ""
|
@ -32,7 +32,7 @@ func Captcha(reqData dataType.UserRequest, ruleSet *config.RuleSet, decision *ac
|
||||
}
|
||||
|
||||
if !verifyClearanceCookie(reqData, *ruleSet) {
|
||||
decision.SetCode(action.Done, []byte("CAPTCHA"))
|
||||
decision.SetResponse(action.Done, []byte("CAPTCHA"), genSessionID(reqData, *ruleSet))
|
||||
return
|
||||
}
|
||||
|
||||
@ -52,6 +52,11 @@ func CheckCaptcha(r *http.Request, reqData dataType.UserRequest, ruleSet *config
|
||||
return
|
||||
}
|
||||
|
||||
if !verifySessionIDCookie(reqData, *ruleSet) {
|
||||
decision.SetResponse(action.Done, []byte("200"), []byte("badSession"))
|
||||
return
|
||||
}
|
||||
|
||||
data := url.Values{}
|
||||
data.Set("secret", ruleSet.CAPTCHARule.HCaptchaSecret)
|
||||
data.Set("response", hCaptchaResponse)
|
||||
@ -130,3 +135,40 @@ func verifyClearanceCookie(reqData dataType.UserRequest, ruleSet config.RuleSet)
|
||||
return hmac.Equal([]byte(computedHash), []byte(expectedHash))
|
||||
|
||||
}
|
||||
|
||||
func genSessionID(reqData dataType.UserRequest, ruleSet config.RuleSet) []byte {
|
||||
timeNow := time.Now().Unix()
|
||||
mac := hmac.New(sha512.New, []byte(ruleSet.CAPTCHARule.SecretKey))
|
||||
mac.Write([]byte(fmt.Sprintf("%d%s%sCAPTCHA-SESSION", timeNow, reqData.Host, utils.GetClearanceUserAgent(reqData.UserAgent))))
|
||||
return []byte(fmt.Sprintf("%s:%s", fmt.Sprintf("%d", time.Now().Unix()), fmt.Sprintf("%x", mac.Sum(nil))))
|
||||
}
|
||||
|
||||
func verifySessionIDCookie(reqData dataType.UserRequest, ruleSet config.RuleSet) bool {
|
||||
if reqData.ToriiSessionID == "" {
|
||||
return false
|
||||
}
|
||||
parts := strings.Split(reqData.ToriiSessionID, ":")
|
||||
if len(parts) != 2 {
|
||||
return false
|
||||
}
|
||||
timestamp := parts[0]
|
||||
expectedHash := parts[1]
|
||||
|
||||
timeNow := time.Now().Unix()
|
||||
parsedTimestamp, err := strconv.ParseInt(timestamp, 10, 64)
|
||||
if err != nil {
|
||||
log.Printf("Error parsing timestamp: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
if timeNow-parsedTimestamp > ruleSet.CAPTCHARule.CaptchaChallengeSessionTimeout {
|
||||
return false
|
||||
}
|
||||
|
||||
mac := hmac.New(sha512.New, []byte(ruleSet.CAPTCHARule.SecretKey))
|
||||
mac.Write([]byte(fmt.Sprintf("%d%s%sCAPTCHA-SESSION", parsedTimestamp, reqData.Host, utils.GetClearanceUserAgent(reqData.UserAgent))))
|
||||
computedHash := fmt.Sprintf("%x", mac.Sum(nil))
|
||||
|
||||
return hmac.Equal([]byte(computedHash), []byte(expectedHash))
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,8 @@ type UserRequest struct {
|
||||
}
|
||||
|
||||
type CaptchaRule struct {
|
||||
SecretKey string `yaml:"secret_key"`
|
||||
CaptchaValidateTime int64 `yaml:"captcha_validate_time"`
|
||||
HCaptchaSecret string `yaml:"hcaptcha_secret"`
|
||||
SecretKey string `yaml:"secret_key"`
|
||||
CaptchaValidateTime int64 `yaml:"captcha_validate_time"`
|
||||
CaptchaChallengeSessionTimeout int64 `yaml:"captcha_challenge_session_timeout"`
|
||||
HCaptchaSecret string `yaml:"hcaptcha_secret"`
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ func CheckMain(w http.ResponseWriter, userRequestData dataType.UserRequest, rule
|
||||
http.Error(w, "500 - Internal Server Error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Set-Cookie", "__torii_session_id="+string(decision.ResponseData)+"; Path=/; Path=/; Max-Age=86400; Priority=High; HttpOnly;")
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
if err = tpl.Execute(w, nil); err != nil {
|
||||
|
@ -28,6 +28,14 @@ func CheckTorii(w http.ResponseWriter, r *http.Request, reqData dataType.UserReq
|
||||
return
|
||||
}
|
||||
return
|
||||
} else if bytes.Compare(decision.ResponseData, []byte("badSession")) == 0 {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, err := w.Write([]byte("badSession"))
|
||||
if err != nil {
|
||||
log.Printf("Error writing response: %v", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
} else if bytes.Compare(decision.ResponseData, []byte("good")) == 0 {
|
||||
w.Header().Set("Set-Cookie", "__torii_clearance="+string(check.GenClearance(reqData, *ruleSet))+"; Path=/; Max-Age=86400; Priority=High; HttpOnly;")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
Reference in New Issue
Block a user