-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
754c48a
commit b0e43b3
Showing
16 changed files
with
602 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
------------------ | ||
captcha | ||
------------------ | ||
# 简单,不依赖第三方框架的一个验证码图片类 | ||
https://github.com/steambap/captcha | ||
|
||
* 支持Gif/Png/Jpeg/算术计算 | ||
|
||
|
||
------------------ | ||
Demo | ||
------------------ | ||
package service | ||
|
||
import ( | ||
"context" | ||
"github.com/gin-gonic/gin" | ||
"github.com/redis/go-redis/v9" | ||
cpt "github.com/steambap/captcha" | ||
"go.uber.org/zap" | ||
"springdoc/common/constant/header" | ||
"springdoc/common/errors" | ||
"springdoc/common/response" | ||
"springdoc/common/util/id" | ||
"springdoc/log" | ||
"springdoc/rdb" | ||
"strconv" | ||
"strings" | ||
"time" | ||
) | ||
|
||
func init() { | ||
// 加载字体 | ||
//err := cpt.LoadFont(goregular.TTF) | ||
//if err != nil { | ||
// panic(err) | ||
//} | ||
} | ||
|
||
type captcha struct { | ||
namespace string | ||
duration time.Duration | ||
} | ||
|
||
func (c captcha) key(id string) string { | ||
return c.namespace + id | ||
} | ||
|
||
// Gen 生成图片验证码 | ||
func (c captcha) Gen(ctx *gin.Context) error { | ||
|
||
// 生成验证码图片 | ||
image, err := cpt.New(150, 50, func(options *cpt.Options) { | ||
options.TextLength = 6 // 字符长度 | ||
options.CurveNumber = 4 // 干扰线数量 | ||
//options.Noise = 4.0 // 噪点数量。默认情况下,每28个像素就画一个噪声点。默认是1.0。 | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// id & 文本 | ||
captchaId := strconv.FormatInt(id.Next(), 10) | ||
text := image.Text | ||
|
||
log.Info("captcha", zap.String("id", captchaId), zap.String("text", text)) | ||
|
||
// 刷到redis缓存 | ||
if err := rdb.Client().Set(context.Background(), c.key(captchaId), text, time.Second*30).Err(); err != nil { | ||
return err | ||
} | ||
|
||
ctx.Header(header.XCaptchaId, captchaId) | ||
ctx.Header(header.ContentType, "image/png") | ||
ctx.Header(header.CacheControl, "no-cache, no-store") | ||
ctx.Header(header.Pragma, "no-cache") | ||
|
||
//return image.WriteGIF(ctx.Writer, &gif.Options{ | ||
// NumColors: 256, // NumColors是图像中使用的最大颜色数。它的范围是1到256。 | ||
// Quantizer: nil, //palette.Plan9被用来代替nil Quantizer,它被用来生成一个具有NumColors大小的调色板。 | ||
// Drawer: nil, // draw.FloydSteinberg用于将源图像转换为所需的调色板。Draw.FloydSteinberg用于替代一个无的Drawer。 | ||
//}) | ||
return image.WriteImage(ctx.Writer) | ||
} | ||
|
||
// Validate 校验验证码是否正确 | ||
func (c captcha) Validate(id string, text string) (bool, error) { | ||
cmd := rdb.Client().GetDel(context.Background(), c.key(id)) | ||
if cmd.Err() == redis.Nil { | ||
return false, errors.New(response.Fail(response.StatusCodeCaptchaRequired).SetMessage("需要验证码")) | ||
} | ||
if cmd.Err() != nil { | ||
return false, cmd.Err() | ||
} | ||
if !strings.EqualFold(cmd.Val(), text) { | ||
return false, errors.New(response.Fail(response.StatusCodeWrongCaptcha).SetMessage("验证码错误")) | ||
} | ||
return true, nil | ||
} | ||
|
||
var Captcha = &captcha{namespace: "CAPTCHA::", duration: time.Second * 30} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
---------------- | ||
EventBus | ||
---------------- | ||
|
||
package bus | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
/* | ||
Bus | ||
https://github.com/grafana/grafana/blob/main/pkg/bus/bus.go | ||
根据 HandlerFunc 的第二个参数类型的名称来确定 Handler | ||
HandlerFunc 函数第一个参数必须是 context, 第二个参数必须是事件对象指针,返回值必须是 error | ||
*/ | ||
|
||
// HandlerFunc defines a handler function interface. | ||
type HandlerFunc any | ||
|
||
// Msg defines a message interface. | ||
type Msg any | ||
|
||
// ErrHandlerNotFound defines an error if a handler is not found. | ||
var ErrHandlerNotFound = errors.New("handler not found") | ||
|
||
// Bus type defines the bus interface structure. | ||
type Bus interface { | ||
Publish(ctx context.Context, msg Msg) error | ||
AddEventListener(handler HandlerFunc) | ||
} | ||
|
||
// InProcBus defines the bus structure. | ||
type InProcBus struct { | ||
listeners map[string][]HandlerFunc | ||
} | ||
|
||
func ProvideBus() *InProcBus { | ||
return &InProcBus{ | ||
listeners: make(map[string][]HandlerFunc), | ||
} | ||
} | ||
|
||
// Publish function publish a message to the bus listener. | ||
func (b *InProcBus) Publish(ctx context.Context, msg Msg) error { | ||
var msgName = reflect.TypeOf(msg).Elem().Name() | ||
|
||
var params []reflect.Value | ||
if listeners, exists := b.listeners[msgName]; exists { | ||
params = append(params, reflect.ValueOf(ctx)) | ||
params = append(params, reflect.ValueOf(msg)) | ||
if err := callListeners(listeners, params); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return ErrHandlerNotFound | ||
} | ||
|
||
func callListeners(listeners []HandlerFunc, params []reflect.Value) error { | ||
for _, listenerHandler := range listeners { | ||
ret := reflect.ValueOf(listenerHandler).Call(params) | ||
e := ret[0].Interface() | ||
if e != nil { | ||
err, ok := e.(error) | ||
if ok { | ||
return err | ||
} | ||
return fmt.Errorf("expected listener to return an error, got '%T'", e) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
func (b *InProcBus) AddEventListener(handler HandlerFunc) { | ||
handlerType := reflect.TypeOf(handler) | ||
eventName := handlerType.In(1).Elem().Name() | ||
_, exists := b.listeners[eventName] | ||
if !exists { | ||
b.listeners[eventName] = make([]HandlerFunc, 0) | ||
} | ||
b.listeners[eventName] = append(b.listeners[eventName], handler) | ||
} | ||
|
||
var bus = ProvideBus() | ||
|
||
func Initialization(listener ...HandlerFunc) { | ||
for _, v := range listener { | ||
bus.AddEventListener(v) | ||
} | ||
} | ||
func Publish(ctx context.Context, msg Msg) error { | ||
return bus.Publish(ctx, msg) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.