+ 验证码
This commit is contained in:
parent
9511ea7e76
commit
823397308f
9 changed files with 317 additions and 2 deletions
4
go.mod
4
go.mod
|
|
@ -19,13 +19,15 @@ require (
|
||||||
github.com/mattn/go-colorable v0.1.10 // indirect
|
github.com/mattn/go-colorable v0.1.10 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.8 // indirect
|
github.com/mattn/go-sqlite3 v1.14.8 // indirect
|
||||||
|
github.com/mojocn/base64Captcha v1.3.5 // indirect
|
||||||
github.com/robertkrimen/otto v0.0.0-20210927222213-f9375a256948 // indirect
|
github.com/robertkrimen/otto v0.0.0-20210927222213-f9375a256948 // indirect
|
||||||
github.com/spf13/cobra v1.2.1 // indirect
|
github.com/spf13/cobra v1.2.1 // indirect
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/yaoapp/gou v0.0.0-20210929042348-e322f26e3a51 // indirect
|
github.com/yaoapp/gou v0.0.0-20210929100518-8de252e7bab8 // indirect
|
||||||
github.com/yaoapp/kun v0.6.3
|
github.com/yaoapp/kun v0.6.3
|
||||||
github.com/yaoapp/xun v0.5.2 // indirect
|
github.com/yaoapp/xun v0.5.2 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
|
||||||
|
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
|
||||||
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b // indirect
|
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b // indirect
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9 // indirect
|
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9 // indirect
|
||||||
|
|
|
||||||
12
go.sum
12
go.sum
|
|
@ -117,6 +117,8 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfC
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
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 v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
|
@ -292,6 +294,10 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/mojocn/base64Captcha v1.2.2 h1:NTFnThPVrb3tR66JO/N8/ZHsyFrNc7ho+xRpxBUEIlo=
|
||||||
|
github.com/mojocn/base64Captcha v1.2.2/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
|
||||||
|
github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
|
||||||
|
github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||||
|
|
@ -359,6 +365,8 @@ github.com/yaoapp/gou v0.0.0-20210929002807-fbe45c391f18 h1:diVG7thFYgqhttHbiGxX
|
||||||
github.com/yaoapp/gou v0.0.0-20210929002807-fbe45c391f18/go.mod h1:KwCRZDnEKLCxUNgMQ2acU7WI5zpt5SGOt1sBKqNAiaE=
|
github.com/yaoapp/gou v0.0.0-20210929002807-fbe45c391f18/go.mod h1:KwCRZDnEKLCxUNgMQ2acU7WI5zpt5SGOt1sBKqNAiaE=
|
||||||
github.com/yaoapp/gou v0.0.0-20210929042348-e322f26e3a51 h1:LlWIuWmbEETkY91qP/yg4mP0VzGde5xO2DmgRGVJfxQ=
|
github.com/yaoapp/gou v0.0.0-20210929042348-e322f26e3a51 h1:LlWIuWmbEETkY91qP/yg4mP0VzGde5xO2DmgRGVJfxQ=
|
||||||
github.com/yaoapp/gou v0.0.0-20210929042348-e322f26e3a51/go.mod h1:mJj2wa3oXVlk/WOHazW8eEZTyva98zDVjIur9lj8aiA=
|
github.com/yaoapp/gou v0.0.0-20210929042348-e322f26e3a51/go.mod h1:mJj2wa3oXVlk/WOHazW8eEZTyva98zDVjIur9lj8aiA=
|
||||||
|
github.com/yaoapp/gou v0.0.0-20210929100518-8de252e7bab8 h1:MPVIqqqF5PV3SEy9a4XNghWoErLp5MQDMDTqA2ikbvw=
|
||||||
|
github.com/yaoapp/gou v0.0.0-20210929100518-8de252e7bab8/go.mod h1:mJj2wa3oXVlk/WOHazW8eEZTyva98zDVjIur9lj8aiA=
|
||||||
github.com/yaoapp/kun v0.6.1 h1:gbjP5wmAuJLe1RGZ2evH4rPCVWykf0iqbksaHikF/GI=
|
github.com/yaoapp/kun v0.6.1 h1:gbjP5wmAuJLe1RGZ2evH4rPCVWykf0iqbksaHikF/GI=
|
||||||
github.com/yaoapp/kun v0.6.1/go.mod h1:igsTcWDnzpp0HtRN7sBP+XOEN2tzoC5hk2MyoPFs3xA=
|
github.com/yaoapp/kun v0.6.1/go.mod h1:igsTcWDnzpp0HtRN7sBP+XOEN2tzoC5hk2MyoPFs3xA=
|
||||||
github.com/yaoapp/kun v0.6.2 h1:QbtdZpVIklRDGEvL5YYRf/eR05YFZVFk/8rX2vy2K0Q=
|
github.com/yaoapp/kun v0.6.2 h1:QbtdZpVIklRDGEvL5YYRf/eR05YFZVFk/8rX2vy2K0Q=
|
||||||
|
|
@ -409,7 +417,11 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
|
||||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
|
||||||
|
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
|
|
||||||
1
main.go
1
main.go
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/yaoapp/xiang/cmd"
|
"github.com/yaoapp/xiang/cmd"
|
||||||
|
_ "github.com/yaoapp/xiang/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 主程序
|
// 主程序
|
||||||
|
|
|
||||||
131
user/captcha.go
Normal file
131
user/captcha.go
Normal file
|
|
@ -0,0 +1,131 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"image/color"
|
||||||
|
|
||||||
|
"github.com/mojocn/base64Captcha"
|
||||||
|
"github.com/yaoapp/kun/exception"
|
||||||
|
)
|
||||||
|
|
||||||
|
var captchaStore = base64Captcha.DefaultMemStore
|
||||||
|
|
||||||
|
// CaptchaOption 验证码配置
|
||||||
|
type CaptchaOption struct {
|
||||||
|
Type string
|
||||||
|
Height int
|
||||||
|
Width int
|
||||||
|
Length int
|
||||||
|
Lang string
|
||||||
|
Background string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCaptchaOption 创建验证码配置
|
||||||
|
func NewCaptchaOption() CaptchaOption {
|
||||||
|
return CaptchaOption{
|
||||||
|
Width: 240,
|
||||||
|
Height: 80,
|
||||||
|
Length: 4,
|
||||||
|
Lang: "zh",
|
||||||
|
Background: "#FFFFFF",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeCaptcha 制作验证码
|
||||||
|
func MakeCaptcha(option CaptchaOption) (string, string) {
|
||||||
|
|
||||||
|
if option.Width == 0 {
|
||||||
|
option.Width = 240
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.Height == 0 {
|
||||||
|
option.Width = 80
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.Length == 0 {
|
||||||
|
option.Length = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.Lang == "" {
|
||||||
|
option.Lang = "zh"
|
||||||
|
}
|
||||||
|
|
||||||
|
var driver base64Captcha.Driver
|
||||||
|
switch option.Type {
|
||||||
|
case "audio":
|
||||||
|
driver = base64Captcha.NewDriverAudio(option.Length, option.Lang)
|
||||||
|
break
|
||||||
|
case "math":
|
||||||
|
background := background(option.Background)
|
||||||
|
driver = base64Captcha.NewDriverMath(
|
||||||
|
option.Height, option.Width, 3,
|
||||||
|
base64Captcha.OptionShowHollowLine, background,
|
||||||
|
base64Captcha.DefaultEmbeddedFonts, []string{},
|
||||||
|
)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
driver = base64Captcha.NewDriverDigit(
|
||||||
|
option.Height, option.Width, 5,
|
||||||
|
0.7, 80,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
c := base64Captcha.NewCaptcha(driver, captchaStore)
|
||||||
|
id, content, err := c.Generate()
|
||||||
|
if err != nil {
|
||||||
|
exception.New("生成验证码出错 %s", 500, err).Throw()
|
||||||
|
}
|
||||||
|
return id, content
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateCaptcha 校验验证码
|
||||||
|
func ValidateCaptcha(id string, value string) bool {
|
||||||
|
return captchaStore.Verify(id, value, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func background(s string) *color.RGBA {
|
||||||
|
if s == "" {
|
||||||
|
s = "#555555"
|
||||||
|
}
|
||||||
|
bg, err := parseHexColorFast(s)
|
||||||
|
if err != nil {
|
||||||
|
exception.New("背景色格式错误 %s", 400, s).Throw()
|
||||||
|
}
|
||||||
|
return &bg
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHexColorFast(s string) (c color.RGBA, err error) {
|
||||||
|
c.A = 0xff
|
||||||
|
|
||||||
|
if s[0] != '#' {
|
||||||
|
return c, errors.New("invalid format")
|
||||||
|
}
|
||||||
|
|
||||||
|
hexToByte := func(b byte) byte {
|
||||||
|
switch {
|
||||||
|
case b >= '0' && b <= '9':
|
||||||
|
return b - '0'
|
||||||
|
case b >= 'a' && b <= 'f':
|
||||||
|
return b - 'a' + 10
|
||||||
|
case b >= 'A' && b <= 'F':
|
||||||
|
return b - 'A' + 10
|
||||||
|
}
|
||||||
|
err = errors.New("invalid format")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
switch len(s) {
|
||||||
|
case 7:
|
||||||
|
c.R = hexToByte(s[1])<<4 + hexToByte(s[2])
|
||||||
|
c.G = hexToByte(s[3])<<4 + hexToByte(s[4])
|
||||||
|
c.B = hexToByte(s[5])<<4 + hexToByte(s[6])
|
||||||
|
case 4:
|
||||||
|
c.R = hexToByte(s[1]) * 17
|
||||||
|
c.G = hexToByte(s[2]) * 17
|
||||||
|
c.B = hexToByte(s[3]) * 17
|
||||||
|
default:
|
||||||
|
err = errors.New("invalid format")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
50
user/process.go
Normal file
50
user/process.go
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/yaoapp/gou"
|
||||||
|
"github.com/yaoapp/kun/any"
|
||||||
|
"github.com/yaoapp/kun/maps"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// 注册处理器
|
||||||
|
gou.RegisterProcessHandler("xiang.user.Captcha", ProcessCaptcha)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessLogin xiang.user.Login 用户登录
|
||||||
|
func ProcessLogin(process *gou.Process) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessCaptcha xiang.user.Captcha 验证码
|
||||||
|
func ProcessCaptcha(process *gou.Process) interface{} {
|
||||||
|
process.ValidateArgNums(1)
|
||||||
|
option := CaptchaOption{
|
||||||
|
Width: any.Of(process.ArgsURLValue(0, "width", "240")).CInt(),
|
||||||
|
Height: any.Of(process.ArgsURLValue(0, "height", "80")).CInt(),
|
||||||
|
Length: any.Of(process.ArgsURLValue(0, "height", "4")).CInt(),
|
||||||
|
Type: process.ArgsURLValue(0, "type", "math"),
|
||||||
|
Background: process.ArgsURLValue(0, "background", "#FFFFFF"),
|
||||||
|
Lang: process.ArgsURLValue(0, "lang", "zh"),
|
||||||
|
}
|
||||||
|
id, content := MakeCaptcha(option)
|
||||||
|
return maps.Map{
|
||||||
|
"id": id,
|
||||||
|
"content": content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessToken xiang.user.Token 使用 Key & Secret 换取 Token
|
||||||
|
func ProcessToken(process *gou.Process) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessTokenRefresh xiang.user.TokenRefresh 刷新Token
|
||||||
|
func ProcessTokenRefresh(process *gou.Process) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessInfo xiang.user.Info 读取当前用户资料
|
||||||
|
func ProcessInfo(process *gou.Process) interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
1
user/user.go
Normal file
1
user/user.go
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
package user
|
||||||
45
user/user_test.go
Normal file
45
user/user_test.go
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
package user
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCaptcha(t *testing.T) {
|
||||||
|
id, content := MakeCaptcha(CaptchaOption{
|
||||||
|
Type: "audio",
|
||||||
|
Width: 240,
|
||||||
|
Height: 80,
|
||||||
|
Length: 4,
|
||||||
|
Lang: "zh",
|
||||||
|
})
|
||||||
|
assert.IsType(t, "string", id)
|
||||||
|
assert.IsType(t, "string", content)
|
||||||
|
captchaStore.Get(id, false)
|
||||||
|
assert.True(t, ValidateCaptcha(id, captchaStore.Get(id, false)))
|
||||||
|
|
||||||
|
id, content = MakeCaptcha(CaptchaOption{
|
||||||
|
Type: "math",
|
||||||
|
Width: 240,
|
||||||
|
Height: 80,
|
||||||
|
Length: 4,
|
||||||
|
Lang: "zh",
|
||||||
|
})
|
||||||
|
assert.IsType(t, "string", id)
|
||||||
|
assert.IsType(t, "string", content)
|
||||||
|
captchaStore.Get(id, false)
|
||||||
|
assert.True(t, ValidateCaptcha(id, captchaStore.Get(id, false)))
|
||||||
|
|
||||||
|
id, content = MakeCaptcha(CaptchaOption{
|
||||||
|
Type: "digit",
|
||||||
|
Width: 240,
|
||||||
|
Height: 80,
|
||||||
|
Length: 4,
|
||||||
|
Lang: "zh",
|
||||||
|
})
|
||||||
|
assert.IsType(t, "string", id)
|
||||||
|
assert.IsType(t, "string", content)
|
||||||
|
captchaStore.Get(id, false)
|
||||||
|
assert.True(t, ValidateCaptcha(id, captchaStore.Get(id, false)))
|
||||||
|
}
|
||||||
62
xiang/apis/user.http.json
Normal file
62
xiang/apis/user.http.json
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
{
|
||||||
|
"name": "系统用户接口",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "系统用户API",
|
||||||
|
"group": "xiang/user",
|
||||||
|
"guard": "bearer-jwt",
|
||||||
|
"paths": [
|
||||||
|
{
|
||||||
|
"path": "/captcha",
|
||||||
|
"method": "GET",
|
||||||
|
"guard": "-",
|
||||||
|
"process": "xiang.user.Captcha",
|
||||||
|
"in": [":query"],
|
||||||
|
"out": {
|
||||||
|
"status": 200,
|
||||||
|
"type": "application/json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/login",
|
||||||
|
"method": "POST",
|
||||||
|
"guard": "-",
|
||||||
|
"process": "xiang.user.Login",
|
||||||
|
"in": ["$payload.email", "$payload.password", "$payload.captcha"],
|
||||||
|
"out": {
|
||||||
|
"status": 200,
|
||||||
|
"type": "application/json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/token",
|
||||||
|
"method": "POST",
|
||||||
|
"guard": "-",
|
||||||
|
"process": "xiang.user.Token",
|
||||||
|
"in": ["$payload.key", "$payload.secret"],
|
||||||
|
"out": {
|
||||||
|
"status": 200,
|
||||||
|
"type": "application/json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/info",
|
||||||
|
"method": "GET",
|
||||||
|
"process": "xiang.user.Info",
|
||||||
|
"in": [],
|
||||||
|
"out": {
|
||||||
|
"status": 200,
|
||||||
|
"type": "application/json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/token/refresh",
|
||||||
|
"method": "GET",
|
||||||
|
"process": "xiang.user.TokenRefresh",
|
||||||
|
"in": [],
|
||||||
|
"out": {
|
||||||
|
"status": 200,
|
||||||
|
"type": "application/json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,18 @@
|
||||||
"path": "/ping",
|
"path": "/ping",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"guard": "-",
|
"guard": "-",
|
||||||
"process": "xiang.global.ping",
|
"process": "xiang.global.Ping",
|
||||||
|
"in": [],
|
||||||
|
"out": {
|
||||||
|
"status": 200,
|
||||||
|
"type": "application/json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "/info",
|
||||||
|
"method": "GET",
|
||||||
|
"guard": "-",
|
||||||
|
"process": "xiang.global.Info",
|
||||||
"in": [],
|
"in": [],
|
||||||
"out": {
|
"out": {
|
||||||
"status": 200,
|
"status": 200,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue