diff --git a/app/stage/auth.html b/app/stage/auth.html
index 8cedecaa2..fba03eaad 100644
--- a/app/stage/auth.html
+++ b/app/stage/auth.html
@@ -437,7 +437,7 @@
} else {
exitApp()
}
- }).catch(() =>{
+ }).catch(() => {
exitApp()
})
} catch (e) {
@@ -462,15 +462,16 @@
}).then((response) => {
if (0 === response.code) {
window.location.href = '/'
- } else {
- document.querySelector('#message').classList.add('b3-snackbar--show')
- document.querySelector('#message').firstElementChild.textContent = response.msg
- inputElement.value = ''
- setTimeout(() => {
- document.querySelector('#message').classList.remove('b3-snackbar--show')
- document.querySelector('#message').firstElementChild.textContent = ''
- }, 6000)
+ return
}
+
+ document.querySelector('#message').classList.add('b3-snackbar--show')
+ document.querySelector('#message').firstElementChild.textContent = response.msg
+ inputElement.value = ''
+ setTimeout(() => {
+ document.querySelector('#message').classList.remove('b3-snackbar--show')
+ document.querySelector('#message').firstElementChild.textContent = ''
+ }, 6000)
})
}
diff --git a/kernel/api/router.go b/kernel/api/router.go
index 370dcf34c..c2d845914 100644
--- a/kernel/api/router.go
+++ b/kernel/api/router.go
@@ -32,6 +32,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/system/uiproc", addUIProcess)
ginServer.Handle("POST", "/api/system/loginAuth", model.LoginAuth)
ginServer.Handle("POST", "/api/system/logoutAuth", model.LogoutAuth)
+ ginServer.Handle("GET", "/api/system/getCaptcha", model.GetCaptcha)
// 需要鉴权
diff --git a/kernel/go.mod b/kernel/go.mod
index 6ec979f0c..cf67502a0 100644
--- a/kernel/go.mod
+++ b/kernel/go.mod
@@ -68,6 +68,7 @@ require (
github.com/go-playground/validator/v10 v10.11.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/goccy/go-json v0.9.8 // indirect
+ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
@@ -106,6 +107,7 @@ require (
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.5.0 // indirect
+ github.com/steambap/captcha v1.4.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
diff --git a/kernel/go.sum b/kernel/go.sum
index b60494d95..2e1f1619a 100644
--- a/kernel/go.sum
+++ b/kernel/go.sum
@@ -199,6 +199,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
+github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
@@ -537,6 +539,8 @@ github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t6
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
+github.com/steambap/captcha v1.4.1 h1:OmMdxLCWCqJvsFaFYwRpvMckIuvI6s8s1LsBrBw97P0=
+github.com/steambap/captcha v1.4.1/go.mod h1:oC9T7IfEgnrhzjDz5Djf1H7GPffCzRMbsQfFkJmhlnk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -621,6 +625,7 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190823064033-3a9bac650e44/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.0.0-20220617043117-41969df76e82 h1:KpZB5pUSBvrHltNEdK/tw0xlPeD13M6M6aGP32gKqiw=
golang.org/x/image v0.0.0-20220617043117-41969df76e82/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
diff --git a/kernel/model/session.go b/kernel/model/session.go
index 11089b034..bdb550492 100644
--- a/kernel/model/session.go
+++ b/kernel/model/session.go
@@ -24,6 +24,7 @@ import (
ginSessions "github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/siyuan-note/siyuan/kernel/util"
+ "github.com/steambap/captcha"
)
func LogoutAuth(c *gin.Context) {
@@ -53,27 +54,83 @@ func LogoutAuth(c *gin.Context) {
func LoginAuth(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
+
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
+ var inputCaptcha string
+ session := util.GetSession(c)
+ if session.NeedCaptcha() {
+ captchaArg := arg["captcha"]
+ if nil == captchaArg {
+ c.Status(400)
+ ret.Code = -1
+ ret.Msg = "need input captcha"
+ return
+ }
+ inputCaptcha = captchaArg.(string)
+
+ if session.Captcha != inputCaptcha {
+ ret.Code = -1
+ ret.Msg = "invalid captcha"
+ return
+ }
+ }
+
authCode := arg["authCode"].(string)
if Conf.AccessAuthCode != authCode {
ret.Code = -1
ret.Msg = Conf.Language(83)
+
+ session.WrongAuthCount++
+ session.Captcha = gulu.Rand.String(7)
+ if session.NeedCaptcha() {
+ ret.Code = 1 // 需要渲染验证码
+ }
+
+ if err := session.Save(c); nil != err {
+ util.LogErrorf("save session failed: " + err.Error())
+ c.Status(500)
+ return
+ }
return
}
- session := &util.SessionData{ID: gulu.Rand.Int(0, 1024), AccessAuthCode: authCode}
+ session.WrongAuthCount = 0
+ session.Captcha = gulu.Rand.String(7)
if err := session.Save(c); nil != err {
- util.LogErrorf("saves session failed: " + err.Error())
- ret.Code = -1
- ret.Msg = "save session failed"
+ util.LogErrorf("save session failed: " + err.Error())
+ c.Status(500)
return
}
}
+func GetCaptcha(c *gin.Context) {
+ img, err := captcha.NewMathExpr(150, 30)
+ if nil != err {
+ util.LogErrorf("generates captcha failed: " + err.Error())
+ c.Status(500)
+ return
+ }
+
+ session := util.GetSession(c)
+ session.Captcha = img.Text
+ if err = session.Save(c); nil != err {
+ util.LogErrorf("save session failed: " + err.Error())
+ c.Status(500)
+ return
+ }
+
+ if err = img.WriteImage(c.Writer); nil != err {
+ util.LogErrorf("writes captcha image failed: " + err.Error())
+ c.Status(500)
+ return
+ }
+ c.Status(200)
+}
+
func CheckReadonly(c *gin.Context) {
if util.ReadOnly {
result := util.NewResult()
diff --git a/kernel/util/session.go b/kernel/util/session.go
index fa663f4f5..1dfb66ae8 100644
--- a/kernel/util/session.go
+++ b/kernel/util/session.go
@@ -26,6 +26,12 @@ import (
type SessionData struct {
ID int
AccessAuthCode string
+ WrongAuthCount int
+ Captcha string
+}
+
+func (sd *SessionData) NeedCaptcha() bool {
+ return 3 < sd.WrongAuthCount
}
// Save saves the current session of the specified context.