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.
196 lines
4.6 KiB
196 lines
4.6 KiB
package jwt |
|
|
|
import ( |
|
"context" |
|
"git.diulo.com/mogfee/kit/errors" |
|
"git.diulo.com/mogfee/kit/middleware" |
|
"git.diulo.com/mogfee/kit/transport" |
|
"git.diulo.com/mogfee/kit/transport/http" |
|
"strings" |
|
) |
|
|
|
const ( |
|
permissionNoCheck = "none" |
|
) |
|
|
|
type userIdKey struct{} |
|
type authKey struct{} |
|
type needAuthKey struct{} |
|
|
|
type GetFromToken func(ctx context.Context) string |
|
type ParseFunc func(ctx context.Context, key string, tokenStr string) (*UserInfo, bool, error) |
|
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 |
|
} |
|
} |
|
|
|
func WithParseFunc(parseFunc ParseFunc) JwtOption { |
|
return func(o *options) { |
|
o.parseFunc = parseFunc |
|
} |
|
} |
|
|
|
func WithGetFromToken(fun GetFromToken) JwtOption { |
|
return func(o *options) { |
|
o.fromToken = fun |
|
} |
|
} |
|
|
|
type options struct { |
|
jwtKey string |
|
fromKey string //cookie:token header:key |
|
//validate func(authKey string) error |
|
//validatePermission func(validatePermission []string, key string) bool |
|
parseFunc ParseFunc |
|
//fromToken GetFromToken |
|
} |
|
|
|
func JWT(opts ...JwtOption) middleware.Middleware { |
|
var cfg = &options{ |
|
jwtKey: "JssLx22bjQwnyqby", |
|
validatePermission: InSlice, |
|
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 |
|
}, |
|
fromToken: func(ctx context.Context) string { |
|
var tokenStr string |
|
if tr, ok := transport.FromServerContext(ctx); ok { |
|
tokenStr = tr.RequestHeader().Get("token") |
|
} |
|
return tokenStr |
|
}, |
|
} |
|
for _, o := range opts { |
|
o(cfg) |
|
} |
|
|
|
return func(handler middleware.Handler) middleware.Handler { |
|
return func(ctx context.Context, a any) (any, error) { |
|
authKey := FromAuthKeyContext(ctx) |
|
needAuth := FromNeedAuthContext(ctx) |
|
autoAuth := FromAutoAuthContext(ctx) |
|
|
|
tokenStr := getTokenStr(ctx, cfg.fromKey) |
|
userInfo, checkOk, err := cfg.parseFunc(ctx, cfg.jwtKey, tokenStr) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
//需要验证 |
|
if needAuth { |
|
if !checkOk { |
|
return nil, errors.Unauthorized("TOKEN_PERMISSION_BAD", "") |
|
} |
|
//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 { |
|
|
|
} |
|
if checkOk { |
|
ctx = SetUserContext(ctx, userInfo) |
|
} |
|
return handler(ctx, a) |
|
} |
|
} |
|
} |
|
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 "" |
|
} |
|
func InSlice(validatePermission []string, key string) bool { |
|
for _, e := range validatePermission { |
|
if e == key { |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
func SetUserContext(ctx context.Context, user *UserInfo) context.Context { |
|
return context.WithValue(ctx, userIdKey{}, user) |
|
} |
|
func FromUserContext(ctx context.Context) (user *UserInfo, ok bool) { |
|
user, ok = ctx.Value(userIdKey{}).(*UserInfo) |
|
return |
|
} |
|
|
|
func SetAuthKeyContext(ctx context.Context, key string) context.Context { |
|
return context.WithValue(ctx, authKey{}, key) |
|
} |
|
func FromAuthKeyContext(ctx context.Context) string { |
|
v := ctx.Value(authKey{}) |
|
if v == nil { |
|
return "" |
|
} |
|
return v.(string) |
|
} |
|
|
|
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) |
|
} |
|
|
|
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) |
|
}
|
|
|