You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
4.6 KiB

2 years ago
package jwt
import (
"context"
"git.diulo.com/mogfee/kit/errors"
"git.diulo.com/mogfee/kit/middleware"
"git.diulo.com/mogfee/kit/transport"
1 year ago
"git.diulo.com/mogfee/kit/transport/http"
"strings"
2 years ago
)
2 years ago
const (
permissionNoCheck = "none"
)
2 years ago
type userIdKey struct{}
2 years ago
type authKey struct{}
type needAuthKey struct{}
2 years ago
1 year ago
type GetFromToken func(ctx context.Context) string
2 years ago
type ParseFunc func(ctx context.Context, key string, tokenStr string) (*UserInfo, bool, error)
2 years ago
type JwtOption func(o *options)
func WithJwtKey(jwtKey string) JwtOption {
return func(o *options) {
o.jwtKey = jwtKey
}
}
func WithValidate(validate func(authKey string) error) JwtOption {
return func(o *options) {
o.validate = validate
}
}
func WithValidatePermission(validatePermission func(permissions []string, key string) bool) JwtOption {
return func(o *options) {
o.validatePermission = validatePermission
}
}
2 years ago
func WithParseFunc(parseFunc ParseFunc) JwtOption {
return func(o *options) {
o.parseFunc = parseFunc
}
}
1 year ago
func WithGetFromToken(fun GetFromToken) JwtOption {
return func(o *options) {
o.fromToken = fun
}
}
2 years ago
type options struct {
1 year ago
jwtKey string
fromKey string //cookie:token header:key
//validate func(authKey string) error
//validatePermission func(validatePermission []string, key string) bool
parseFunc ParseFunc
//fromToken GetFromToken
2 years ago
}
func JWT(opts ...JwtOption) middleware.Middleware {
var cfg = &options{
jwtKey: "JssLx22bjQwnyqby",
validatePermission: InSlice,
2 years ago
parseFunc: func(ctx context.Context, key string, tokenStr string) (*UserInfo, bool, error) {
userInfo, err := Parse(key, tokenStr)
if err != nil {
return nil, false, err
}
return userInfo, userInfo.UserId > 0, nil
},
1 year ago
fromToken: func(ctx context.Context) string {
var tokenStr string
if tr, ok := transport.FromServerContext(ctx); ok {
tokenStr = tr.RequestHeader().Get("token")
}
return tokenStr
},
2 years ago
}
for _, o := range opts {
o(cfg)
}
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, a any) (any, error) {
2 years ago
authKey := FromAuthKeyContext(ctx)
needAuth := FromNeedAuthContext(ctx)
1 year ago
autoAuth := FromAutoAuthContext(ctx)
2 years ago
1 year ago
tokenStr := getTokenStr(ctx, cfg.fromKey)
2 years ago
userInfo, checkOk, err := cfg.parseFunc(ctx, cfg.jwtKey, tokenStr)
2 years ago
if err != nil {
return nil, err
}
1 year ago
2 years ago
//需要验证
if needAuth {
2 years ago
if !checkOk {
return nil, errors.Unauthorized("TOKEN_PERMISSION_BAD", "")
}
1 year ago
//if authKey != "" {
// if !cfg.validatePermission(userInfo.Permissions, authKey) {
// return nil, errors.Unauthorized("TOKEN_PERMISSION_BAD", "")
// }
//}
//if cfg.validate != nil {
// if err = cfg.validate(userInfo.UniqueId); err != nil {
// return nil, err
// }
//}
} else if autoAuth {
} else {
2 years ago
}
2 years ago
if checkOk {
ctx = SetUserContext(ctx, userInfo)
}
2 years ago
return handler(ctx, a)
}
}
}
1 year ago
func getTokenStr(ctx context.Context, fromKey string) string {
arr := strings.Split(fromKey, ":")
if len(arr) != 2 {
return ""
}
switch arr[0] {
case "cookie":
if tr, ok := transport.FromServerContext(ctx); ok {
if tr1, ok := tr.(http.Transporter); ok {
if co, err := tr1.Request().Cookie(arr[1]); err == nil {
return co.Value
}
}
}
case "header":
if tr, ok := transport.FromServerContext(ctx); ok {
return tr.RequestHeader().Get(arr[1])
}
}
return ""
}
2 years ago
func InSlice(validatePermission []string, key string) bool {
for _, e := range validatePermission {
if e == key {
return true
}
}
return false
}
2 years ago
func SetUserContext(ctx context.Context, user *UserInfo) context.Context {
2 years ago
return context.WithValue(ctx, userIdKey{}, user)
}
2 years ago
func FromUserContext(ctx context.Context) (user *UserInfo, ok bool) {
user, ok = ctx.Value(userIdKey{}).(*UserInfo)
2 years ago
return
}
func SetAuthKeyContext(ctx context.Context, key string) context.Context {
return context.WithValue(ctx, authKey{}, key)
}
func FromAuthKeyContext(ctx context.Context) string {
2 years ago
v := ctx.Value(authKey{})
if v == nil {
return ""
}
return v.(string)
2 years ago
}
2 years ago
func SetNeedAuthContext(ctx context.Context, auth bool) context.Context {
return context.WithValue(ctx, needAuthKey{}, auth)
}
func FromNeedAuthContext(ctx context.Context) bool {
v := ctx.Value(needAuthKey{})
if v == nil {
return false
}
return v.(bool)
}
1 year ago
type autoAuthKey struct {
}
func SetAutoAuthContext(ctx context.Context, autoAuth bool) context.Context {
return context.WithValue(ctx, autoAuthKey{}, autoAuth)
}
func FromAutoAuthContext(ctx context.Context) bool {
v := ctx.Value(autoAuthKey{})
if v == nil {
return false
}
return v.(bool)
}