mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-27 06:03:51 +03:00
Add option to enable CAPTCHA validation for login (#21638)
Enable this to require captcha validation for user login. You also must enable `ENABLE_CAPTCHA`. Summary: - Consolidate CAPTCHA template - add CAPTCHA handle and context - add `REQUIRE_CAPTCHA_FOR_LOGIN` config and docs - Consolidate CAPTCHA set-up and verification code Partially resolved #6049 Signed-off-by: Xinyu Zhou <i@sourcehut.net> Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
parent
e77b76425e
commit
68e934ab5d
14 changed files with 128 additions and 180 deletions
|
@ -759,6 +759,9 @@ ROUTER = console
|
||||||
;; Enable captcha validation for registration
|
;; Enable captcha validation for registration
|
||||||
;ENABLE_CAPTCHA = false
|
;ENABLE_CAPTCHA = false
|
||||||
;;
|
;;
|
||||||
|
;; Enable this to require captcha validation for login
|
||||||
|
;REQUIRE_CAPTCHA_FOR_LOGIN = false
|
||||||
|
;;
|
||||||
;; Type of captcha you want to use. Options: image, recaptcha, hcaptcha, mcaptcha.
|
;; Type of captcha you want to use. Options: image, recaptcha, hcaptcha, mcaptcha.
|
||||||
;CAPTCHA_TYPE = image
|
;CAPTCHA_TYPE = image
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -634,6 +634,7 @@ Certain queues have defaults that override the defaults set in `[queue]` (this o
|
||||||
- `ENABLE_REVERSE_PROXY_FULL_NAME`: **false**: Enable this to allow to auto-registration with a
|
- `ENABLE_REVERSE_PROXY_FULL_NAME`: **false**: Enable this to allow to auto-registration with a
|
||||||
provided full name for the user.
|
provided full name for the user.
|
||||||
- `ENABLE_CAPTCHA`: **false**: Enable this to use captcha validation for registration.
|
- `ENABLE_CAPTCHA`: **false**: Enable this to use captcha validation for registration.
|
||||||
|
- `REQUIRE_CAPTCHA_FOR_LOGIN`: **false**: Enable this to require captcha validation for login. You also must enable `ENABLE_CAPTCHA`.
|
||||||
- `REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA`: **false**: Enable this to force captcha validation
|
- `REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA`: **false**: Enable this to force captcha validation
|
||||||
even for External Accounts (i.e. GitHub, OpenID Connect, etc). You also must enable `ENABLE_CAPTCHA`.
|
even for External Accounts (i.e. GitHub, OpenID Connect, etc). You also must enable `ENABLE_CAPTCHA`.
|
||||||
- `CAPTCHA_TYPE`: **image**: \[image, recaptcha, hcaptcha, mcaptcha\]
|
- `CAPTCHA_TYPE`: **image**: \[image, recaptcha, hcaptcha, mcaptcha\]
|
||||||
|
|
|
@ -145,7 +145,8 @@ menu:
|
||||||
- `ENABLE_NOTIFY_MAIL`: 是否发送工单创建等提醒邮件,需要 `Mailer` 被激活。
|
- `ENABLE_NOTIFY_MAIL`: 是否发送工单创建等提醒邮件,需要 `Mailer` 被激活。
|
||||||
- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: 允许反向代理认证,更多细节见:https://github.com/gogits/gogs/issues/165
|
- `ENABLE_REVERSE_PROXY_AUTHENTICATION`: 允许反向代理认证,更多细节见:https://github.com/gogits/gogs/issues/165
|
||||||
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: 允许通过反向认证做自动注册。
|
- `ENABLE_REVERSE_PROXY_AUTO_REGISTRATION`: 允许通过反向认证做自动注册。
|
||||||
- `ENABLE_CAPTCHA`: 注册时使用图片验证码。
|
- `ENABLE_CAPTCHA`: **false**: 注册时使用图片验证码。
|
||||||
|
- `REQUIRE_CAPTCHA_FOR_LOGIN`: **false**: 登录时需要图片验证码。需要同时开启 `ENABLE_CAPTCHA`。
|
||||||
|
|
||||||
### Service - Expore (`service.explore`)
|
### Service - Expore (`service.explore`)
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,15 @@
|
||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/cache"
|
"code.gitea.io/gitea/modules/cache"
|
||||||
|
"code.gitea.io/gitea/modules/hcaptcha"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/mcaptcha"
|
||||||
|
"code.gitea.io/gitea/modules/recaptcha"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"gitea.com/go-chi/captcha"
|
"gitea.com/go-chi/captcha"
|
||||||
|
@ -28,3 +34,56 @@ func GetImageCaptcha() *captcha.Captcha {
|
||||||
})
|
})
|
||||||
return cpt
|
return cpt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCaptchaData sets common captcha data
|
||||||
|
func SetCaptchaData(ctx *Context) {
|
||||||
|
if !setting.Service.EnableCaptcha {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
|
||||||
|
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
|
||||||
|
ctx.Data["Captcha"] = GetImageCaptcha()
|
||||||
|
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
|
||||||
|
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
|
||||||
|
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
||||||
|
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
||||||
|
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
gRecaptchaResponseField = "g-recaptcha-response"
|
||||||
|
hCaptchaResponseField = "h-captcha-response"
|
||||||
|
mCaptchaResponseField = "m-captcha-response"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VerifyCaptcha verifies Captcha data
|
||||||
|
// No-op if captchas are not enabled
|
||||||
|
func VerifyCaptcha(ctx *Context, tpl base.TplName, form interface{}) {
|
||||||
|
if !setting.Service.EnableCaptcha {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var valid bool
|
||||||
|
var err error
|
||||||
|
switch setting.Service.CaptchaType {
|
||||||
|
case setting.ImageCaptcha:
|
||||||
|
valid = GetImageCaptcha().VerifyReq(ctx.Req)
|
||||||
|
case setting.ReCaptcha:
|
||||||
|
valid, err = recaptcha.Verify(ctx, ctx.Req.Form.Get(gRecaptchaResponseField))
|
||||||
|
case setting.HCaptcha:
|
||||||
|
valid, err = hcaptcha.Verify(ctx, ctx.Req.Form.Get(hCaptchaResponseField))
|
||||||
|
case setting.MCaptcha:
|
||||||
|
valid, err = mcaptcha.Verify(ctx, ctx.Req.Form.Get(mCaptchaResponseField))
|
||||||
|
default:
|
||||||
|
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !valid {
|
||||||
|
ctx.Data["Err_Captcha"] = true
|
||||||
|
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tpl, form)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ var Service = struct {
|
||||||
EnableReverseProxyEmail bool
|
EnableReverseProxyEmail bool
|
||||||
EnableReverseProxyFullName bool
|
EnableReverseProxyFullName bool
|
||||||
EnableCaptcha bool
|
EnableCaptcha bool
|
||||||
|
RequireCaptchaForLogin bool
|
||||||
RequireExternalRegistrationCaptcha bool
|
RequireExternalRegistrationCaptcha bool
|
||||||
RequireExternalRegistrationPassword bool
|
RequireExternalRegistrationPassword bool
|
||||||
CaptchaType string
|
CaptchaType string
|
||||||
|
@ -130,6 +131,7 @@ func newService() {
|
||||||
Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool()
|
Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool()
|
||||||
Service.EnableReverseProxyFullName = sec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool()
|
Service.EnableReverseProxyFullName = sec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool()
|
||||||
Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
|
Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
|
||||||
|
Service.RequireCaptchaForLogin = sec.Key("REQUIRE_CAPTCHA_FOR_LOGIN").MustBool(false)
|
||||||
Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool(Service.EnableCaptcha)
|
Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool(Service.EnableCaptcha)
|
||||||
Service.RequireExternalRegistrationPassword = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_PASSWORD").MustBool()
|
Service.RequireExternalRegistrationPassword = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_PASSWORD").MustBool()
|
||||||
Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha)
|
Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha)
|
||||||
|
|
|
@ -17,11 +17,8 @@ import (
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/eventsource"
|
"code.gitea.io/gitea/modules/eventsource"
|
||||||
"code.gitea.io/gitea/modules/hcaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/mcaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/password"
|
"code.gitea.io/gitea/modules/password"
|
||||||
"code.gitea.io/gitea/modules/recaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/session"
|
"code.gitea.io/gitea/modules/session"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
@ -163,6 +160,10 @@ func SignIn(ctx *context.Context) {
|
||||||
ctx.Data["PageIsLogin"] = true
|
ctx.Data["PageIsLogin"] = true
|
||||||
ctx.Data["EnableSSPI"] = auth.IsSSPIEnabled()
|
ctx.Data["EnableSSPI"] = auth.IsSSPIEnabled()
|
||||||
|
|
||||||
|
if setting.Service.EnableCaptcha && setting.Service.RequireCaptchaForLogin {
|
||||||
|
context.SetCaptchaData(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
ctx.HTML(http.StatusOK, tplSignIn)
|
ctx.HTML(http.StatusOK, tplSignIn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +190,16 @@ func SignInPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
form := web.GetForm(ctx).(*forms.SignInForm)
|
form := web.GetForm(ctx).(*forms.SignInForm)
|
||||||
|
|
||||||
|
if setting.Service.EnableCaptcha && setting.Service.RequireCaptchaForLogin {
|
||||||
|
context.SetCaptchaData(ctx)
|
||||||
|
|
||||||
|
context.VerifyCaptcha(ctx, tplSignIn, form)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u, source, err := auth_service.UserSignIn(form.UserName, form.Password)
|
u, source, err := auth_service.UserSignIn(form.UserName, form.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if user_model.IsErrUserNotExist(err) || user_model.IsErrEmailAddressNotExist(err) {
|
if user_model.IsErrUserNotExist(err) || user_model.IsErrEmailAddressNotExist(err) {
|
||||||
|
@ -383,14 +394,7 @@ func SignUp(ctx *context.Context) {
|
||||||
|
|
||||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
|
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
|
||||||
|
|
||||||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
|
context.SetCaptchaData(ctx)
|
||||||
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
|
|
||||||
ctx.Data["Captcha"] = context.GetImageCaptcha()
|
|
||||||
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
|
|
||||||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
|
|
||||||
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
|
||||||
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
|
||||||
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
|
||||||
ctx.Data["PageIsSignUp"] = true
|
ctx.Data["PageIsSignUp"] = true
|
||||||
|
|
||||||
// Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true
|
// Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true
|
||||||
|
@ -406,14 +410,7 @@ func SignUpPost(ctx *context.Context) {
|
||||||
|
|
||||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
|
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
|
||||||
|
|
||||||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
|
context.SetCaptchaData(ctx)
|
||||||
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
|
|
||||||
ctx.Data["Captcha"] = context.GetImageCaptcha()
|
|
||||||
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
|
|
||||||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
|
|
||||||
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
|
||||||
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
|
||||||
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
|
||||||
ctx.Data["PageIsSignUp"] = true
|
ctx.Data["PageIsSignUp"] = true
|
||||||
|
|
||||||
// Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
|
// Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
|
||||||
|
@ -427,31 +424,9 @@ func SignUpPost(ctx *context.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.Service.EnableCaptcha {
|
context.VerifyCaptcha(ctx, tplSignUp, form)
|
||||||
var valid bool
|
if ctx.Written() {
|
||||||
var err error
|
return
|
||||||
switch setting.Service.CaptchaType {
|
|
||||||
case setting.ImageCaptcha:
|
|
||||||
valid = context.GetImageCaptcha().VerifyReq(ctx.Req)
|
|
||||||
case setting.ReCaptcha:
|
|
||||||
valid, err = recaptcha.Verify(ctx, form.GRecaptchaResponse)
|
|
||||||
case setting.HCaptcha:
|
|
||||||
valid, err = hcaptcha.Verify(ctx, form.HcaptchaResponse)
|
|
||||||
case setting.MCaptcha:
|
|
||||||
valid, err = mcaptcha.Verify(ctx, form.McaptchaResponse)
|
|
||||||
default:
|
|
||||||
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("%s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if !valid {
|
|
||||||
ctx.Data["Err_Captcha"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplSignUp, &form)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !form.IsEmailDomainAllowed() {
|
if !form.IsEmailDomainAllowed() {
|
||||||
|
|
|
@ -14,10 +14,6 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/hcaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/mcaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/recaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
auth_service "code.gitea.io/gitea/services/auth"
|
auth_service "code.gitea.io/gitea/services/auth"
|
||||||
|
@ -221,28 +217,8 @@ func LinkAccountPostRegister(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.Service.EnableCaptcha && setting.Service.RequireExternalRegistrationCaptcha {
|
if setting.Service.EnableCaptcha && setting.Service.RequireExternalRegistrationCaptcha {
|
||||||
var valid bool
|
context.VerifyCaptcha(ctx, tplLinkAccount, form)
|
||||||
var err error
|
if ctx.Written() {
|
||||||
switch setting.Service.CaptchaType {
|
|
||||||
case setting.ImageCaptcha:
|
|
||||||
valid = context.GetImageCaptcha().VerifyReq(ctx.Req)
|
|
||||||
case setting.ReCaptcha:
|
|
||||||
valid, err = recaptcha.Verify(ctx, form.GRecaptchaResponse)
|
|
||||||
case setting.HCaptcha:
|
|
||||||
valid, err = hcaptcha.Verify(ctx, form.HcaptchaResponse)
|
|
||||||
case setting.MCaptcha:
|
|
||||||
valid, err = mcaptcha.Verify(ctx, form.McaptchaResponse)
|
|
||||||
default:
|
|
||||||
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("%s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if !valid {
|
|
||||||
ctx.Data["Err_Captcha"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplLinkAccount, &form)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/auth/openid"
|
"code.gitea.io/gitea/modules/auth/openid"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/hcaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/mcaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/recaptcha"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/modules/web"
|
"code.gitea.io/gitea/modules/web"
|
||||||
|
@ -357,14 +354,7 @@ func RegisterOpenIDPost(ctx *context.Context) {
|
||||||
ctx.Data["PageIsSignIn"] = true
|
ctx.Data["PageIsSignIn"] = true
|
||||||
ctx.Data["PageIsOpenIDRegister"] = true
|
ctx.Data["PageIsOpenIDRegister"] = true
|
||||||
ctx.Data["EnableOpenIDSignUp"] = setting.Service.EnableOpenIDSignUp
|
ctx.Data["EnableOpenIDSignUp"] = setting.Service.EnableOpenIDSignUp
|
||||||
ctx.Data["EnableCaptcha"] = setting.Service.EnableCaptcha
|
context.SetCaptchaData(ctx)
|
||||||
ctx.Data["RecaptchaURL"] = setting.Service.RecaptchaURL
|
|
||||||
ctx.Data["Captcha"] = context.GetImageCaptcha()
|
|
||||||
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
|
|
||||||
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
|
|
||||||
ctx.Data["HcaptchaSitekey"] = setting.Service.HcaptchaSitekey
|
|
||||||
ctx.Data["McaptchaSitekey"] = setting.Service.McaptchaSitekey
|
|
||||||
ctx.Data["McaptchaURL"] = setting.Service.McaptchaURL
|
|
||||||
ctx.Data["OpenID"] = oid
|
ctx.Data["OpenID"] = oid
|
||||||
|
|
||||||
if setting.Service.AllowOnlyInternalRegistration {
|
if setting.Service.AllowOnlyInternalRegistration {
|
||||||
|
@ -373,42 +363,11 @@ func RegisterOpenIDPost(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if setting.Service.EnableCaptcha {
|
if setting.Service.EnableCaptcha {
|
||||||
var valid bool
|
if err := ctx.Req.ParseForm(); err != nil {
|
||||||
var err error
|
ctx.ServerError("", err)
|
||||||
switch setting.Service.CaptchaType {
|
|
||||||
case setting.ImageCaptcha:
|
|
||||||
valid = context.GetImageCaptcha().VerifyReq(ctx.Req)
|
|
||||||
case setting.ReCaptcha:
|
|
||||||
if err := ctx.Req.ParseForm(); err != nil {
|
|
||||||
ctx.ServerError("", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
valid, err = recaptcha.Verify(ctx, form.GRecaptchaResponse)
|
|
||||||
case setting.HCaptcha:
|
|
||||||
if err := ctx.Req.ParseForm(); err != nil {
|
|
||||||
ctx.ServerError("", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
valid, err = hcaptcha.Verify(ctx, form.HcaptchaResponse)
|
|
||||||
case setting.MCaptcha:
|
|
||||||
if err := ctx.Req.ParseForm(); err != nil {
|
|
||||||
ctx.ServerError("", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
valid, err = mcaptcha.Verify(ctx, form.McaptchaResponse)
|
|
||||||
default:
|
|
||||||
ctx.ServerError("Unknown Captcha Type", fmt.Errorf("Unknown Captcha Type: %s", setting.Service.CaptchaType))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
log.Debug("%s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
if !valid {
|
|
||||||
ctx.Data["Err_Captcha"] = true
|
|
||||||
ctx.RenderWithErr(ctx.Tr("form.captcha_incorrect"), tplSignUpOID, &form)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
context.VerifyCaptcha(ctx, tplSignUpOID, form)
|
||||||
}
|
}
|
||||||
|
|
||||||
length := setting.MinPasswordLength
|
length := setting.MinPasswordLength
|
||||||
|
|
|
@ -91,13 +91,10 @@ func (f *InstallForm) Validate(req *http.Request, errs binding.Errors) binding.E
|
||||||
|
|
||||||
// RegisterForm form for registering
|
// RegisterForm form for registering
|
||||||
type RegisterForm struct {
|
type RegisterForm struct {
|
||||||
UserName string `binding:"Required;Username;MaxSize(40)"`
|
UserName string `binding:"Required;Username;MaxSize(40)"`
|
||||||
Email string `binding:"Required;MaxSize(254)"`
|
Email string `binding:"Required;MaxSize(254)"`
|
||||||
Password string `binding:"MaxSize(255)"`
|
Password string `binding:"MaxSize(255)"`
|
||||||
Retype string
|
Retype string
|
||||||
GRecaptchaResponse string `form:"g-recaptcha-response"`
|
|
||||||
HcaptchaResponse string `form:"h-captcha-response"`
|
|
||||||
McaptchaResponse string `form:"m-captcha-response"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
|
|
|
@ -27,11 +27,8 @@ func (f *SignInOpenIDForm) Validate(req *http.Request, errs binding.Errors) bind
|
||||||
|
|
||||||
// SignUpOpenIDForm form for signin up with OpenID
|
// SignUpOpenIDForm form for signin up with OpenID
|
||||||
type SignUpOpenIDForm struct {
|
type SignUpOpenIDForm struct {
|
||||||
UserName string `binding:"Required;Username;MaxSize(40)"`
|
UserName string `binding:"Required;Username;MaxSize(40)"`
|
||||||
Email string `binding:"Required;Email;MaxSize(254)"`
|
Email string `binding:"Required;Email;MaxSize(254)"`
|
||||||
GRecaptchaResponse string `form:"g-recaptcha-response"`
|
|
||||||
HcaptchaResponse string `form:"h-captcha-response"`
|
|
||||||
McaptchaResponse string `form:"m-captcha-response"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates the fields
|
// Validate validates the fields
|
||||||
|
|
24
templates/user/auth/captcha.tmpl
Normal file
24
templates/user/auth/captcha.tmpl
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{{if .EnableCaptcha}}{{if eq .CaptchaType "image"}}
|
||||||
|
<div class="inline field">
|
||||||
|
<label>{{/* This is CAPTCHA field */}}</label>
|
||||||
|
{{.Captcha.CreateHTML}}
|
||||||
|
</div>
|
||||||
|
<div class="required inline field {{if .Err_Captcha}}error{{end}}">
|
||||||
|
<label for="captcha">{{.locale.Tr "captcha"}}</label>
|
||||||
|
<input id="captcha" name="captcha" value="{{.captcha}}" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
{{else if eq .CaptchaType "recaptcha"}}
|
||||||
|
<div class="inline field required">
|
||||||
|
<div class="g-recaptcha" data-sitekey="{{.RecaptchaSitekey}}"></div>
|
||||||
|
</div>
|
||||||
|
{{else if eq .CaptchaType "hcaptcha"}}
|
||||||
|
<div class="inline field required">
|
||||||
|
<div class="h-captcha" data-sitekey="{{.HcaptchaSitekey}}"></div>
|
||||||
|
</div>
|
||||||
|
{{else if eq .CaptchaType "mcaptcha"}}
|
||||||
|
<div class="inline field df ac db-small captcha-field">
|
||||||
|
<span>{{.locale.Tr "captcha"}}</span>
|
||||||
|
<div class="border-secondary w-100-small" id="mcaptcha__widget-container" style="width: 50%; height: 5em"></div>
|
||||||
|
<div class="m-captcha" data-sitekey="{{.McaptchaSitekey}}" data-instance-url="{{.McaptchaURL}}"></div>
|
||||||
|
</div>
|
||||||
|
{{end}}{{end}}
|
|
@ -31,6 +31,8 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
{{template "user/auth/captcha" .}}
|
||||||
|
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<label></label>
|
<label></label>
|
||||||
<button class="ui green button">
|
<button class="ui green button">
|
||||||
|
|
|
@ -34,34 +34,8 @@
|
||||||
<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="new-password" required>
|
<input id="retype" name="retype" type="password" value="{{.retype}}" autocomplete="new-password" required>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "image")}}
|
|
||||||
<div class="inline field">
|
|
||||||
<label></label>
|
|
||||||
{{.Captcha.CreateHTML}}
|
|
||||||
</div>
|
|
||||||
<div class="required inline field {{if .Err_Captcha}}error{{end}}">
|
|
||||||
<label for="captcha">{{.locale.Tr "captcha"}}</label>
|
|
||||||
<input id="captcha" name="captcha" value="{{.captcha}}" autocomplete="off">
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "recaptcha")}}
|
|
||||||
<div class="inline field required">
|
|
||||||
<div class="g-recaptcha" data-sitekey="{{.RecaptchaSitekey}}"></div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "hcaptcha")}}
|
|
||||||
<div class="inline field required">
|
|
||||||
<div class="h-captcha" data-sitekey="{{.HcaptchaSitekey}}"></div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "mcaptcha")}}
|
|
||||||
<div class="inline field df ac db-small captcha-field">
|
|
||||||
<span>{{.locale.Tr "captcha"}}</span>
|
|
||||||
<div class="border-secondary w-100-small" id="mcaptcha__widget-container" style="width: 50%; height: 5em"></div>
|
|
||||||
<div class="m-captcha" data-sitekey="{{.McaptchaSitekey}}" data-instance-url="{{.McaptchaURL}}"></div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
|
|
||||||
|
{{template "user/auth/captcha" .}}
|
||||||
|
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<label></label>
|
<label></label>
|
||||||
|
|
|
@ -20,31 +20,9 @@
|
||||||
<label for="email">{{.locale.Tr "email"}}</label>
|
<label for="email">{{.locale.Tr "email"}}</label>
|
||||||
<input id="email" name="email" type="email" value="{{.email}}" required>
|
<input id="email" name="email" type="email" value="{{.email}}" required>
|
||||||
</div>
|
</div>
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "image")}}
|
|
||||||
<div class="inline field">
|
{{template "user/auth/captcha" .}}
|
||||||
<label></label>
|
|
||||||
{{.Captcha.CreateHTML}}
|
|
||||||
</div>
|
|
||||||
<div class="required inline field {{if .Err_Captcha}}error{{end}}">
|
|
||||||
<label for="captcha">{{.locale.Tr "captcha"}}</label>
|
|
||||||
<input id="captcha" name="captcha" value="{{.captcha}}" autocomplete="off">
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "recaptcha")}}
|
|
||||||
<div class="inline field required">
|
|
||||||
<div class="g-recaptcha" data-sitekey="{{.RecaptchaSitekey}}"></div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "hcaptcha")}}
|
|
||||||
<div class="inline field required">
|
|
||||||
<div class="h-captcha" data-sitekey="{{.HcaptchaSitekey}}"></div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
{{if and .EnableCaptcha (eq .CaptchaType "mcaptcha")}}
|
|
||||||
<div class="inline field required">
|
|
||||||
<div class="m-captcha" data-sitekey="{{.McaptchaSitekey}}" data-instance-url="{{.McaptchaURL}}"></div>
|
|
||||||
</div>
|
|
||||||
{{end}}
|
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<label for="openid">OpenID URI</label>
|
<label for="openid">OpenID URI</label>
|
||||||
<input id="openid" value="{{.OpenID}}" readonly>
|
<input id="openid" value="{{.OpenID}}" readonly>
|
||||||
|
|
Loading…
Reference in a new issue