mirror of
https://github.com/eolinker/apinto
synced 2025-11-01 20:42:42 +08:00
修复aksk query参数顺序未按字母排序问题
This commit is contained in:
@@ -6,33 +6,47 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
http_service "github.com/eolinker/eosc/eocontext/http-context"
|
http_service "github.com/eolinker/eosc/eocontext/http-context"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dateHeader = "x-gateway-date"
|
const dateHeader = "x-gateway-date"
|
||||||
|
|
||||||
//buildToSign 构建待加密的签名所需字符串
|
// buildToSign 构建待加密的签名所需字符串
|
||||||
func buildToSign(ctx http_service.IHttpContext, encType string, signedHeaders []string) string {
|
func buildToSign(ctx http_service.IHttpContext, encType string, signedHeaders []string) string {
|
||||||
toSign := strings.Builder{}
|
toSign := strings.Builder{}
|
||||||
toSign.WriteString(encType + "\n")
|
toSign.WriteString(encType + "\n")
|
||||||
dh := ctx.Request().Header().GetHeader(dateHeader)
|
dh := ctx.Request().Header().GetHeader(dateHeader)
|
||||||
toSign.WriteString(dh + "\n")
|
toSign.WriteString(dh + "\n")
|
||||||
|
|
||||||
cr := buildHexCanonicalRequest(ctx, signedHeaders)
|
cr := buildHexCanonicalRequest(ctx, signedHeaders)
|
||||||
toSign.WriteString(strings.ToLower(cr))
|
toSign.WriteString(strings.ToLower(cr))
|
||||||
return toSign.String()
|
return toSign.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
//buildHexCanonicalRequest 构建规范消息头
|
// buildHexCanonicalRequest 构建规范消息头
|
||||||
func buildHexCanonicalRequest(ctx http_service.IHttpContext, signedHeaders []string) string {
|
func buildHexCanonicalRequest(ctx http_service.IHttpContext, signedHeaders []string) string {
|
||||||
cr := strings.Builder{}
|
cr := strings.Builder{}
|
||||||
|
|
||||||
cr.WriteString(strings.ToUpper(ctx.Request().Method()) + "\n")
|
cr.WriteString(strings.ToUpper(ctx.Request().Method()) + "\n")
|
||||||
cr.WriteString(buildPath(ctx.Request().URI().Path()) + "\n")
|
cr.WriteString(buildPath(ctx.Request().URI().Path()) + "\n")
|
||||||
cr.WriteString(ctx.Request().URI().RawQuery() + "\n")
|
// 对query参数排序
|
||||||
|
rawQuery := ctx.Request().URI().RawQuery()
|
||||||
|
query := url.Values{}
|
||||||
|
queryArgs := strings.Split(strings.TrimSpace(rawQuery), "&")
|
||||||
|
for i := 0; i < len(queryArgs); i++ {
|
||||||
|
params := strings.Split(queryArgs[i], "=")
|
||||||
|
if len(params) != 2 {
|
||||||
|
//query.Set(params[0], "")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
query.Set(params[0], params[1])
|
||||||
|
}
|
||||||
|
cr.WriteString(query.Encode() + "\n")
|
||||||
|
//cr.WriteString(ctx.Request().URI().RawQuery() + "\n")
|
||||||
|
|
||||||
for _, header := range signedHeaders {
|
for _, header := range signedHeaders {
|
||||||
if strings.ToLower(header) == "host" {
|
if strings.ToLower(header) == "host" {
|
||||||
cr.WriteString(buildHeaders(header, ctx.Request().Header().Host()) + "\n")
|
cr.WriteString(buildHeaders(header, ctx.Request().Header().Host()) + "\n")
|
||||||
@@ -45,7 +59,7 @@ func buildHexCanonicalRequest(ctx http_service.IHttpContext, signedHeaders []str
|
|||||||
cr.WriteString(strings.Join(signedHeaders, ";") + "\n")
|
cr.WriteString(strings.Join(signedHeaders, ";") + "\n")
|
||||||
body, _ := ctx.Request().Body().RawBody()
|
body, _ := ctx.Request().Body().RawBody()
|
||||||
cr.WriteString(hexEncode(body))
|
cr.WriteString(hexEncode(body))
|
||||||
|
|
||||||
return hexEncode([]byte(cr.String()))
|
return hexEncode([]byte(cr.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +86,7 @@ func hMaxBySHA256(secretKey, toSign string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseAuthorization(token string) (encType string, accessKey string, signHeaders []string, signature string, err error) {
|
func parseAuthorization(token string) (encType string, accessKey string, signHeaders []string, signature string, err error) {
|
||||||
|
|
||||||
infos := strings.Split(token, ",")
|
infos := strings.Split(token, ",")
|
||||||
if len(infos) < 3 {
|
if len(infos) < 3 {
|
||||||
err = errors.New("invalid authorization")
|
err = errors.New("invalid authorization")
|
||||||
@@ -83,9 +97,9 @@ func parseAuthorization(token string) (encType string, accessKey string, signHea
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
signHeaders = parseSignHeaders(infos[1])
|
signHeaders = parseSignHeaders(infos[1])
|
||||||
|
|
||||||
signature = parseSignature(infos[2])
|
signature = parseSignature(infos[2])
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
35
application/auth/aksk/sign_test.go
Normal file
35
application/auth/aksk/sign_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package aksk
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
http_context "github.com/eolinker/apinto/node/http-context"
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAksk_Check(t *testing.T) {
|
||||||
|
req := fasthttp.AcquireRequest()
|
||||||
|
u := fasthttp.AcquireURI()
|
||||||
|
uri, _ := url.Parse("https://gateway.hr-soft.cn/api/redapi/tech/redteams/tag/tagUser?userId=8e211885-b622-11ec-8e03-14187749a8c0&tagId=37")
|
||||||
|
u.SetPath(uri.Path)
|
||||||
|
u.SetScheme(uri.Scheme)
|
||||||
|
u.SetHost(uri.Host)
|
||||||
|
u.SetQueryString(uri.RawQuery)
|
||||||
|
req.SetURI(u)
|
||||||
|
req.SetHostBytes(u.Host())
|
||||||
|
req.Header.Set("x-gateway-date", "20200605T104456Z")
|
||||||
|
req.Header.Set("content-type", "application/json")
|
||||||
|
req.Header.SetHostBytes(u.Host())
|
||||||
|
|
||||||
|
ctx := &fasthttp.RequestCtx{
|
||||||
|
Request: *req,
|
||||||
|
}
|
||||||
|
origin := buildToSign(http_context.NewContext(ctx, 9000), "HMAC-SHA256", []string{"content-type", "host", "x-gateway-date"})
|
||||||
|
t.Log("origin", origin)
|
||||||
|
sign := hMaxBySHA256("8f8154ff07f7153eea59a2ba44b5fcfe443dba1e4c45f87c549e6a05f699145d", origin)
|
||||||
|
if sign != "523a1d901873fbbc19df355dba6f8bb695a2ef3435206615e7724490054b0529" {
|
||||||
|
t.Fatalf("sign error %s", sign)
|
||||||
|
}
|
||||||
|
t.Logf("sign %s", sign)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package websocket
|
package websocket
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,6 +15,9 @@ import (
|
|||||||
var dialer = &websocket.Dialer{
|
var dialer = &websocket.Dialer{
|
||||||
Proxy: http.ProxyFromEnvironment,
|
Proxy: http.ProxyFromEnvironment,
|
||||||
HandshakeTimeout: 45 * time.Second,
|
HandshakeTimeout: 45 * time.Second,
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var skipHeaders = []string{
|
var skipHeaders = []string{
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package fasthttp_client
|
package fasthttp_client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@@ -22,7 +23,7 @@ func ProxyTimeout(scheme string, host string, node eocontext.INode, req *fasthtt
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultClient Client
|
var defaultClient = NewClient()
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultMaxConns = 10240
|
DefaultMaxConns = 10240
|
||||||
@@ -38,9 +39,21 @@ const (
|
|||||||
//
|
//
|
||||||
// The fields of a Client should not be changed while it is in use.
|
// The fields of a Client should not be changed while it is in use.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
mLock sync.Mutex
|
mLock sync.RWMutex
|
||||||
m map[string]*fasthttp.HostClient
|
m map[string]*fasthttp.HostClient
|
||||||
ms map[string]*fasthttp.HostClient
|
ms map[string]*fasthttp.HostClient
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient() *Client {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
return &Client{
|
||||||
|
m: make(map[string]*fasthttp.HostClient),
|
||||||
|
ms: make(map[string]*fasthttp.HostClient),
|
||||||
|
ctx: ctx,
|
||||||
|
cancel: cancel,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readAddress(addr string) (scheme, host string) {
|
func readAddress(addr string) (scheme, host string) {
|
||||||
@@ -54,31 +67,31 @@ func (c *Client) getHostClient(addr string, rewriteHost string) (*fasthttp.HostC
|
|||||||
|
|
||||||
scheme, nodeAddr := readAddress(addr)
|
scheme, nodeAddr := readAddress(addr)
|
||||||
host := nodeAddr
|
host := nodeAddr
|
||||||
isTLS := false
|
isTLS := strings.EqualFold(scheme, "https")
|
||||||
if strings.EqualFold(scheme, "https") {
|
|
||||||
isTLS = true
|
|
||||||
host = fmt.Sprintf("%s-%s", rewriteHost, nodeAddr)
|
|
||||||
|
|
||||||
} else if !strings.EqualFold(scheme, "http") {
|
if !strings.EqualFold(scheme, "http") && !isTLS {
|
||||||
return nil, "", fmt.Errorf("unsupported protocol %q. http and https are supported", scheme)
|
return nil, "", fmt.Errorf("unsupported protocol %q. http and https are supported", scheme)
|
||||||
}
|
}
|
||||||
|
|
||||||
startCleaner := false
|
c.mLock.RLock()
|
||||||
|
|
||||||
c.mLock.Lock()
|
|
||||||
m := c.m
|
m := c.m
|
||||||
if isTLS {
|
if isTLS {
|
||||||
m = c.ms
|
m = c.ms
|
||||||
}
|
}
|
||||||
if m == nil {
|
|
||||||
m = make(map[string]*fasthttp.HostClient)
|
|
||||||
if isTLS {
|
|
||||||
c.ms = m
|
|
||||||
} else {
|
|
||||||
c.m = m
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hc := m[host]
|
hc := m[host]
|
||||||
|
c.mLock.RUnlock()
|
||||||
|
if hc != nil {
|
||||||
|
return hc, scheme, nil
|
||||||
|
}
|
||||||
|
c.mLock.Lock()
|
||||||
|
defer c.mLock.Unlock()
|
||||||
|
|
||||||
|
if isTLS {
|
||||||
|
m = c.ms
|
||||||
|
} else {
|
||||||
|
m = c.m
|
||||||
|
}
|
||||||
if hc == nil {
|
if hc == nil {
|
||||||
dial := Dial
|
dial := Dial
|
||||||
dialAddr := addMissingPort(nodeAddr, isTLS)
|
dialAddr := addMissingPort(nodeAddr, isTLS)
|
||||||
@@ -109,14 +122,10 @@ func (c *Client) getHostClient(addr string, rewriteHost string) (*fasthttp.HostC
|
|||||||
}
|
}
|
||||||
m[host] = hc
|
m[host] = hc
|
||||||
if len(m) == 1 {
|
if len(m) == 1 {
|
||||||
startCleaner = true
|
go c.startCleaner(m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.mLock.Unlock()
|
|
||||||
|
|
||||||
if startCleaner {
|
|
||||||
go c.mCleaner(m)
|
|
||||||
}
|
|
||||||
return hc, scheme, nil
|
return hc, scheme, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,39 +168,42 @@ func (c *Client) ProxyTimeout(addr string, host string, req *fasthttp.Request, r
|
|||||||
resp.SetConnectionClose()
|
resp.SetConnectionClose()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
//var deadline time.Time
|
|
||||||
//var requestURI string
|
|
||||||
//redirectCount := 0
|
|
||||||
//for {
|
|
||||||
client, scheme, err := c.getHostClient(addr, host)
|
client, scheme, err := c.getHostClient(addr, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
request.URI().SetScheme(scheme)
|
request.URI().SetScheme(scheme)
|
||||||
|
|
||||||
//if redirectCount == 0 {
|
|
||||||
// deadline = time.Now().Add(timeout)
|
|
||||||
//} else {
|
|
||||||
// request.SetRequestURI(requestURI)
|
|
||||||
//}
|
|
||||||
//log.Info("requestURI:", request.URI().String()+", host:", request.Host(), " body:", string(request.Body()))
|
|
||||||
return client.DoTimeout(req, resp, timeout)
|
return client.DoTimeout(req, resp, timeout)
|
||||||
//if err != nil {
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
//if !fasthttp.StatusCodeIsRedirect(resp.StatusCode()) || redirectCount >= DefaultMaxRedirectCount {
|
|
||||||
// break
|
|
||||||
//}
|
|
||||||
//redirectCount++
|
|
||||||
//location := resp.Header.Peek("Location")
|
|
||||||
//if len(location) == 0 {
|
|
||||||
// return fasthttp.ErrMissingLocation
|
|
||||||
//}
|
|
||||||
//addr, requestURI = getRedirectURL(req.URI().String(), location)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//return nil
|
}
|
||||||
|
|
||||||
|
func (c *Client) startCleaner(m map[string]*fasthttp.HostClient) {
|
||||||
|
sleep := time.Second * 10
|
||||||
|
mustStop := false
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-c.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-time.After(sleep):
|
||||||
|
c.mLock.Lock()
|
||||||
|
for k, v := range m {
|
||||||
|
if v.ConnsCount() == 0 {
|
||||||
|
v.CloseIdleConnections()
|
||||||
|
delete(m, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(m) == 0 {
|
||||||
|
mustStop = true
|
||||||
|
}
|
||||||
|
c.mLock.Unlock()
|
||||||
|
if mustStop {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) mCleaner(m map[string]*fasthttp.HostClient) {
|
func (c *Client) mCleaner(m map[string]*fasthttp.HostClient) {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ func (ur *URIRequest) GetQuery(key string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ur *URIRequest) RawQuery() string {
|
func (ur *URIRequest) RawQuery() string {
|
||||||
return string(ur.uri.QueryArgs().String())
|
return ur.uri.QueryArgs().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ur *URIRequest) SetPath(s string) {
|
func (ur *URIRequest) SetPath(s string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user