Files
higress/plugins/wasm-go/extensions/jwt-auth/handler/extractor.go
2024-06-06 10:22:51 +08:00

147 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2023 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package handler
import (
"net/url"
"strings"
cfg "github.com/alibaba/higress/plugins/wasm-go/extensions/jwt-auth/config"
)
// extracToken 从三个来源中依次尝试抽取Token若找不到Token则返回空字符串
func extractToken(keepToken bool, consumer *cfg.Consumer, header HeaderProvider, log Logger) string {
token := ""
// 1. 从header中抽取token
if h := consumer.FromHeaders; h != nil {
token = extractFromHeader(keepToken, *h, header, log)
}
if token != "" {
return token
}
// 2. 从params中抽取token
if p := consumer.FromParams; p != nil {
token = extractFromParams(keepToken, *p, header, log)
}
if token != "" {
return token
}
// 3. 从cookies中抽取token
if c := consumer.FromCookies; c != nil {
token = extractFromCookies(keepToken, *c, header, log)
}
// 此处无需判空
return token
}
func extractFromHeader(keepToken bool, headers []cfg.FromHeader, header HeaderProvider, log Logger) (token string) {
for i := range headers {
// proxywasm 获取到的 header name 均为小写,此处需做修改
lowerName := strings.ToLower(headers[i].Name)
token, err := header.GetHttpRequestHeader(lowerName)
if err != nil {
log.Warnf("failed to get authorization: %v", err)
continue
}
if token != "" {
if !strings.HasPrefix(token, headers[i].ValuePrefix) {
log.Warnf("authorization has no prefix %q", headers[i].ValuePrefix)
return ""
}
if !keepToken {
_ = header.RemoveHttpRequestHeader(lowerName)
}
return strings.TrimPrefix(token, headers[i].ValuePrefix)
}
}
return ""
}
func extractFromParams(keepToken bool, params []string, header HeaderProvider, log Logger) (token string) {
urlparams, err := header.GetHttpRequestHeader(":path")
if err != nil {
log.Warnf("failed to get authorization: %v", err)
return ""
}
url, _ := url.Parse(urlparams)
query := url.Query()
for i := range params {
token := query.Get(params[i])
if token != "" {
if !keepToken {
query.Del(params[i])
}
return token
}
}
return ""
}
func extractFromCookies(keepToken bool, cookies []string, header HeaderProvider, log Logger) (token string) {
requestCookies, err := header.GetHttpRequestHeader("cookie")
if err != nil {
log.Warnf("failed to get authorization: %v", err)
return ""
}
for i := range cookies {
token := findCookie(requestCookies, cookies[i])
if token != "" {
if !keepToken {
_ = header.ReplaceHttpRequestHeader("cookie", deleteCookie(requestCookies, cookies[i]))
}
return token
}
}
return ""
}
func findCookie(cookie string, key string) string {
value := ""
pairs := strings.Split(cookie, ";")
for _, pair := range pairs {
pair = strings.TrimSpace(pair)
kv := strings.Split(pair, "=")
if kv[0] == key {
value = kv[1]
break
}
}
return value
}
func deleteCookie(cookie string, key string) string {
result := ""
pairs := strings.Split(cookie, ";")
for _, pair := range pairs {
pair = strings.TrimSpace(pair)
if !strings.HasPrefix(pair, key) {
result += pair + ";"
}
}
return strings.TrimSuffix(result, ";")
}