-
Notifications
You must be signed in to change notification settings - Fork 4
/
middleware_jwt.go
132 lines (111 loc) · 2.88 KB
/
middleware_jwt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package echox
import (
`fmt`
`net/http`
`reflect`
`strings`
`github.com/dgrijalva/jwt-go`
`github.com/labstack/echo/v4`
)
// AlgorithmHS256 HS256加密算法
const AlgorithmHS256 = "HS256"
var errJwtMissing = echo.NewHTTPError(http.StatusUnauthorized, "缺失Jwt请求头")
type (
// 成功后的处理方法
jwtSuccessHandler func(echo.Context)
jwtExtractor func(echo.Context) (string, error)
)
// JwtMiddleware Jwt中间件
func JwtMiddleware(config *Jwt) MiddlewareFunc {
config.keyFunc = func(t *jwt.Token) (key interface{}, err error) {
if t.Method.Alg() != config.method {
err = fmt.Errorf("未知的签名算法=%v", t.Header["alg"])
} else {
key = []byte(config.key.(string))
}
return
}
for _, lookup := range config.lookups {
parts := strings.Split(lookup, ":")
switch parts[0] {
case "header":
config.extractor = append(config.extractor, jwtFromHeader(parts[1], config.scheme))
case "query":
config.extractor = append(config.extractor, jwtFromQuery(parts[1]))
case "cookie":
config.extractor = append(config.extractor, jwtFromCookie(parts[1]))
}
}
return func(next handlerFunc) handlerFunc {
return func(ctx *Context) (err error) {
if config.skipper(ctx) {
err = next(ctx)
return
}
if nil != config.beforeHandler {
config.beforeHandler(ctx)
}
var authToken string
if authToken, err = config.runExtractor(ctx); nil != err {
return
}
token := new(jwt.Token)
if _, ok := config.claims.(jwt.MapClaims); ok {
token, err = jwt.Parse(authToken, config.keyFunc)
} else {
t := reflect.ValueOf(config.claims).Type().Elem()
claims := reflect.New(t).Interface().(jwt.Claims)
token, err = jwt.ParseWithClaims(authToken, claims, config.keyFunc)
}
if nil != err {
return
}
if token.Valid {
ctx.Set(config.context, token)
if nil != config.successHandler {
config.successHandler(ctx)
}
err = next(ctx)
} else {
err = &echo.HTTPError{
Code: http.StatusUnauthorized,
Message: "JWT错误或者已经失效",
Internal: err,
}
}
return
}
}
}
func jwtFromHeader(header string, authScheme string) jwtExtractor {
return func(ctx echo.Context) (token string, err error) {
auth := ctx.Request().Header.Get(header)
authLength := len(authScheme)
if len(auth) > authLength+1 && auth[:authLength] == authScheme {
token = auth[authLength+1:]
} else {
err = errJwtMissing
}
return
}
}
func jwtFromQuery(param string) jwtExtractor {
return func(ctx echo.Context) (token string, err error) {
token = ctx.QueryParam(param)
if "" == token {
err = errJwtMissing
}
return
}
}
func jwtFromCookie(name string) jwtExtractor {
return func(ctx echo.Context) (token string, err error) {
var cookie *http.Cookie
if cookie, err = ctx.Cookie(name); nil != err {
err = errJwtMissing
} else {
token = cookie.Value
}
return
}
}