diff --git a/authentication/authentication_client.go b/authentication/authentication_client.go index c1b3d1c..beb0787 100644 --- a/authentication/authentication_client.go +++ b/authentication/authentication_client.go @@ -11,9 +11,8 @@ import ( "github.com/Authing/authing-golang-sdk/v3/constant" "github.com/Authing/authing-golang-sdk/v3/dto" "github.com/Authing/authing-golang-sdk/v3/util" - - keyfunc "github.com/MicahParks/compatibility-keyfunc" - "github.com/dgrijalva/jwt-go" + "github.com/MicahParks/keyfunc/v2" + "github.com/golang-jwt/jwt/v5" "github.com/valyala/fasthttp" ) @@ -27,9 +26,10 @@ var commonHeaders = map[string]string{ } type AuthenticationClient struct { - options *AuthenticationClientOptions - jwks *keyfunc.JWKS - eventHub *util.WebSocketEventHub + httpClient *fasthttp.Client + options *AuthenticationClientOptions + jwks *keyfunc.JWKS + eventHub *util.WebSocketEventHub } func NewAuthenticationClient(options *AuthenticationClientOptions) (*AuthenticationClient, error) { @@ -68,6 +68,7 @@ func NewAuthenticationClient(options *AuthenticationClientOptions) (*Authenticat options: options, eventHub: util.NewWebSocketEvent(), } + client.httpClient = client.createHttpClient() return client, nil } @@ -481,19 +482,19 @@ func (client *AuthenticationClient) getKeyCommon(token *jwt.Token) (interface{}, if err != nil { return nil, fmt.Errorf("获取 JWKS 失败 %v", err) } - return jwks.KeyfuncLegacy(token) + return jwks.Keyfunc(token) } func (client *AuthenticationClient) getKey4IdToken(token *jwt.Token) (interface{}, error) { claims := token.Claims.(*IDTokenClaims) - claims.IssuedAt = 0 + claims.IssuedAt = jwt.NewNumericDate(time.Now()) return client.getKeyCommon(token) } func (client *AuthenticationClient) getKey4AccessToken(token *jwt.Token) (interface{}, error) { claims := token.Claims.(*AccessTokenClaims) - claims.IssuedAt = 0 + claims.IssuedAt = jwt.NewNumericDate(time.Now()) return client.getKeyCommon(token) } diff --git a/authentication/authentication_http_client.go b/authentication/authentication_http_client.go index 722609b..d033573 100644 --- a/authentication/authentication_http_client.go +++ b/authentication/authentication_http_client.go @@ -1,53 +1,41 @@ package authentication import ( - "bytes" "crypto/tls" "encoding/base64" "encoding/json" "fmt" + "github.com/Authing/authing-golang-sdk/v3/constant" "github.com/Authing/authing-golang-sdk/v3/util" "github.com/valyala/fasthttp" - "strings" ) func (client *AuthenticationClient) SendHttpRequest(url string, method string, reqDto interface{}) ([]byte, error) { - var buf bytes.Buffer - err := json.NewEncoder(&buf).Encode(reqDto) - if err != nil { - return nil, err - } req := fasthttp.AcquireRequest() defer fasthttp.ReleaseRequest(req) - data, _ := json.Marshal(&reqDto) - variables := make(map[string]interface{}) - json.Unmarshal(data, &variables) - - var queryString strings.Builder + reqJsonBytes, err := json.Marshal(&reqDto) + if err != nil { + return nil, err + } if method == fasthttp.MethodGet { - if variables != nil && len(variables) > 0 { - for key, value := range variables { - queryString.WriteString(key) - queryString.WriteString("=") - queryString.WriteString(fmt.Sprintf("%v", value)) - queryString.WriteString("&") - } + variables := make(map[string]interface{}) + err = json.Unmarshal(reqJsonBytes, &variables) + if err != nil { + return nil, err } - qs := queryString.String() - if qs != "" { - url += "?" + qs + queryString := util.GetQueryString2(variables) + if queryString != "" { + url += "?" + queryString } } + // 设置请求方法 + req.Header.SetMethod(method) // 设置请求地址 req.SetRequestURI(client.options.AppHost + url) - // 设置请求头 - if method != fasthttp.MethodGet { - req.Header.Add("Content-Type", "application/json;charset=UTF-8") - } //req.Header.Add("x-authing-request-from", c.options.RequestFrom) req.Header.Add("x-authing-sdk-version", constant.SdkVersion) //req.Header.Add("x-authing-lang", c.Lang) @@ -69,24 +57,16 @@ func (client *AuthenticationClient) SendHttpRequest(url string, method string, r } else if client.options.AccessToken != "" { req.Header.Add("authorization", client.options.AccessToken) } + req.Header.Add("Content-Type", "application/json;charset=UTF-8") - // 设置请求方法 - req.Header.SetMethod(method) - - bytes, err := json.Marshal(reqDto) //data是请求数据 - - if err != nil { - return nil, err + if method != fasthttp.MethodGet { + req.SetBody(reqJsonBytes) } - req.SetBody(bytes) + resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseResponse(resp) - httpClient := &fasthttp.Client{ - TLSConfig: &tls.Config{InsecureSkipVerify: client.options.InsecureSkipVerify}, - } - - err = httpClient.DoTimeout(req, resp, client.options.ReadTimeout) + err = client.httpClient.DoTimeout(req, resp, client.options.ReadTimeout) if err != nil { resultMap := make(map[string]interface{}) if err == fasthttp.ErrTimeout { @@ -105,3 +85,14 @@ func (client *AuthenticationClient) SendHttpRequest(url string, method string, r body := resp.Body() return body, err } + +func (client *AuthenticationClient) createHttpClient() *fasthttp.Client { + options := client.options + createClientFunc := options.CreateClientFunc + if createClientFunc != nil { + return createClientFunc(options) + } + return &fasthttp.Client{ + TLSConfig: &tls.Config{InsecureSkipVerify: options.InsecureSkipVerify}, + } +} diff --git a/authentication/authentication_options.go b/authentication/authentication_options.go index 1d10adf..8079c01 100644 --- a/authentication/authentication_options.go +++ b/authentication/authentication_options.go @@ -1,8 +1,10 @@ package authentication import ( - "github.com/dgrijalva/jwt-go" "time" + + "github.com/golang-jwt/jwt/v5" + "github.com/valyala/fasthttp" ) type AuthenticationClientOptions struct { @@ -85,6 +87,10 @@ type AuthenticationClientOptions struct { * 订阅事件 WebSocket 地址 */ WssHost string + /** + * 自定义 Client 创建函数 + */ + CreateClientFunc func(options *AuthenticationClientOptions) *fasthttp.Client } type AuthUrlResult struct { @@ -156,14 +162,14 @@ type IDTokenExtended struct { type IDTokenClaims struct { UserInfoCommon IDTokenExtended - jwt.StandardClaims + jwt.RegisteredClaims } type AccessTokenExtended struct { Scope string `json:"scope,omitempty"` } type AccessTokenClaims struct { - jwt.StandardClaims + jwt.RegisteredClaims AccessTokenExtended } diff --git a/authentication/authentication_protocol_http_client.go b/authentication/authentication_protocol_http_client.go index e06015a..be1b774 100644 --- a/authentication/authentication_protocol_http_client.go +++ b/authentication/authentication_protocol_http_client.go @@ -1,11 +1,11 @@ package authentication import ( - "crypto/tls" "encoding/json" "fmt" + + "github.com/Authing/authing-golang-sdk/v3/util" "github.com/valyala/fasthttp" - "net/url" ) type ContentType int @@ -29,23 +29,6 @@ type ResponseData struct { StatusCode int } -func GenQueryString(variables map[string]string) string { - params := url.Values{} - for key, value := range variables { - params.Add(key, fmt.Sprintf("%v", value)) - } - qs := params.Encode() - return qs -} - -func GenFormArgs(variables map[string]string) *fasthttp.Args { - args := &fasthttp.Args{} - for key, value := range variables { - args.Add(key, fmt.Sprintf("%v", value)) - } - return args -} - func (client AuthenticationClient) SendProtocolHttpRequest(option *ProtocolRequestOption) (*ResponseData, error) { req := fasthttp.AcquireRequest() defer fasthttp.ReleaseRequest(req) @@ -53,52 +36,46 @@ func (client AuthenticationClient) SendProtocolHttpRequest(option *ProtocolReque method := option.Method reqDto := option.ReqDto url := option.Url - if method == fasthttp.MethodGet && reqDto != nil { - variables := reqDto - qs := GenQueryString(variables) - if qs != "" { - url += "?" + qs - } + queryString := util.GetQueryString(reqDto) + if method == fasthttp.MethodGet && queryString != "" { + url += "?" + queryString } + req.Header.SetMethod(method) req.SetRequestURI(url) + for key, value := range option.Headers { req.Header.Add(key, value) } - req.Header.SetMethod(method) resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseResponse(resp) - if option.ContentType == Json { - req.Header.SetContentType("application/json; charset=UTF-8") - bytes, err := json.Marshal(reqDto) //序列化json - if err != nil { - return &ResponseData{ - StatusCode: 500, - }, err - } - req.SetBody(bytes) - - } else if method == fasthttp.MethodPost { - req.Header.SetContentType("application/x-www-form-urlencoded; charset=UTF-8") - if reqDto != nil { - variables := reqDto - bytes := GenFormArgs(variables).QueryString() + switch method { + case fasthttp.MethodPost: + if option.ContentType == Json { + req.Header.SetContentType("application/json; charset=UTF-8") + bytes, err := json.Marshal(reqDto) //序列化json + if err != nil { + return &ResponseData{ + StatusCode: 500, + }, err + } req.SetBody(bytes) + } else { + req.Header.SetContentType("application/x-www-form-urlencoded; charset=UTF-8") + if queryString != "" { + req.SetBodyString(queryString) + } } - } else if method == fasthttp.MethodGet { - - } else { + case fasthttp.MethodGet: + default: return &ResponseData{ StatusCode: 500, }, fmt.Errorf("不支持的请求类型") } - httpClient := &fasthttp.Client{ - TLSConfig: &tls.Config{InsecureSkipVerify: client.options.InsecureSkipVerify}, - } - err := httpClient.DoTimeout(req, resp, client.options.ReadTimeout) + err := client.httpClient.DoTimeout(req, resp, client.options.ReadTimeout) if err != nil { return &ResponseData{ StatusCode: 500, diff --git a/go.mod b/go.mod index 64741f5..b6688f4 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/Authing/authing-golang-sdk/v3 go 1.8 require ( - github.com/MicahParks/compatibility-keyfunc v0.14.0 - github.com/dgrijalva/jwt-go v3.2.0+incompatible - github.com/gorilla/websocket v1.5.0 // indirect + github.com/MicahParks/keyfunc/v2 v2.1.0 + github.com/golang-jwt/jwt/v5 v5.0.0 + github.com/gorilla/websocket v1.5.0 github.com/klauspost/compress v1.15.2 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible github.com/valyala/fasthttp v1.36.0 diff --git a/go.sum b/go.sum index 94ec094..1a8a44a 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,9 @@ -github.com/MicahParks/compatibility-keyfunc v0.14.0 h1:VRRQiygqgRcNfTetVM0gqHc2Gl4vn2R0wT2Ph37Qi9M= -github.com/MicahParks/compatibility-keyfunc v0.14.0/go.mod h1:J3Oey5Hj4gxFX8F6lQMms2F9sYhrTzWvsLYIDvz/EFs= +github.com/MicahParks/keyfunc/v2 v2.1.0 h1:6ZXKb9Rp6qp1bDbJefnG7cTH8yMN1IC/4nf+GVjO99k= +github.com/MicahParks/keyfunc/v2 v2.1.0/go.mod h1:rW42fi+xgLJ2FRRXAfNx9ZA8WpD4OeE/yHVMteCkw9k= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8= -github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= diff --git a/management/management_client_options.go b/management/management_client_options.go index ea5b81f..cefd31a 100644 --- a/management/management_client_options.go +++ b/management/management_client_options.go @@ -1,15 +1,15 @@ package management import ( - "net/http" "time" "github.com/Authing/authing-golang-sdk/v3/constant" "github.com/Authing/authing-golang-sdk/v3/util" + "github.com/valyala/fasthttp" ) type ManagementClient struct { - HttpClient *http.Client + httpClient *fasthttp.Client options *ManagementClientOptions userPoolId string eventHub *util.WebSocketEventHub @@ -29,6 +29,10 @@ type ManagementClientOptions struct { */ InsecureSkipVerify bool WssHost string + /** + * 自定义 Client 创建函数 + */ + CreateClientFunc func(options *ManagementClientOptions) *fasthttp.Client } func NewManagementClient(options *ManagementClientOptions) (*ManagementClient, error) { @@ -45,17 +49,7 @@ func NewManagementClient(options *ManagementClientOptions) (*ManagementClient, e options: options, } - if c.HttpClient == nil { - c.HttpClient = &http.Client{} - _, err := GetAccessToken(c) - if err != nil { - return nil, err - } - /*src := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: accessToken}, - ) - c.HttpClient = oauth2.NewManagementClient(context.Background(), src)*/ - } + c.httpClient = c.createHttpClient() c.eventHub = util.NewWebSocketEvent() return c, nil } diff --git a/management/management_http_client.go b/management/management_http_client.go index cb5eeda..3594b6e 100644 --- a/management/management_http_client.go +++ b/management/management_http_client.go @@ -3,20 +3,19 @@ package management import ( "crypto/tls" "encoding/json" - "fmt" - url2 "net/url" "sync" "time" "github.com/Authing/authing-golang-sdk/v3/constant" "github.com/Authing/authing-golang-sdk/v3/dto" + "github.com/Authing/authing-golang-sdk/v3/util" "github.com/Authing/authing-golang-sdk/v3/util/cache" - "github.com/dgrijalva/jwt-go" + "github.com/golang-jwt/jwt/v5" "github.com/valyala/fasthttp" ) type JwtClaims struct { - *jwt.StandardClaims + *jwt.RegisteredClaims //用户编号 UID string Username string @@ -67,54 +66,48 @@ func QueryAccessToken(client *ManagementClient) (*dto.GetManagementTokenRespDto, return &r, nil } -func (c *ManagementClient) SendHttpRequest(url string, method string, reqDto interface{}) ([]byte, error) { +func (client *ManagementClient) SendHttpRequest(url string, method string, reqDto interface{}) ([]byte, error) { req := fasthttp.AcquireRequest() defer fasthttp.ReleaseRequest(req) - data, _ := json.Marshal(&reqDto) - variables := make(map[string]interface{}) - json.Unmarshal(data, &variables) - - if method == fasthttp.MethodGet && variables != nil && len(variables) > 0 { - params := url2.Values{} - urlTemp, _ := url2.Parse(url) - for key, value := range variables { - params.Set(key, fmt.Sprintf("%v", value)) + reqJsonBytes, err := json.Marshal(&reqDto) + if err != nil { + return nil, err + } + if method == fasthttp.MethodGet { + variables := make(map[string]interface{}) + err = json.Unmarshal(reqJsonBytes, &variables) + if err != nil { + return nil, err + } + queryString := util.GetQueryString2(variables) + if queryString != "" { + url += "?" + queryString } - urlTemp.RawQuery = params.Encode() - url = urlTemp.String() } - req.SetRequestURI(c.options.Host + url) + req.Header.SetMethod(method) + req.SetRequestURI(client.options.Host + url) - if method != fasthttp.MethodGet { - req.Header.Add("Content-Type", "application/json;charset=UTF-8") - } - req.Header.Add("x-authing-app-tenant-id", ""+c.options.TenantId) - //req.Header.Add("x-authing-request-from", c.options.RequestFrom) + req.Header.Add("x-authing-app-tenant-id", client.options.TenantId) + //req.Header.Add("x-authing-request-from", client.options.RequestFrom) req.Header.Add("x-authing-sdk-version", constant.SdkVersion) - req.Header.Add("x-authing-lang", c.options.Lang) + req.Header.Add("x-authing-lang", client.options.Lang) if url != "/api/v3/get-management-token" { - token, _ := GetAccessToken(c) + token, _ := GetAccessToken(client) req.Header.Add("Authorization", "Bearer "+token) - req.Header.Add("x-authing-userpool-id", c.userPoolId) + req.Header.Add("x-authing-userpool-id", client.userPoolId) } - req.Header.SetMethod(method) + req.Header.Add("Content-Type", "application/json;charset=UTF-8") - bytes, err := json.Marshal(reqDto) //data是请求数据 - - if err != nil { - return nil, err + if method != fasthttp.MethodGet { + req.SetBody(reqJsonBytes) } - req.SetBody(bytes) + resp := fasthttp.AcquireResponse() defer fasthttp.ReleaseResponse(resp) - client := &fasthttp.Client{ - TLSConfig: &tls.Config{InsecureSkipVerify: true}, - } - - err = client.DoTimeout(req, resp, c.options.ReadTimeout) + err = client.httpClient.DoTimeout(req, resp, client.options.ReadTimeout) if err != nil { resultMap := make(map[string]interface{}) if err == fasthttp.ErrTimeout { @@ -133,3 +126,14 @@ func (c *ManagementClient) SendHttpRequest(url string, method string, reqDto int body := resp.Body() return body, err } + +func (client *ManagementClient) createHttpClient() *fasthttp.Client { + options := client.options + createClientFunc := options.CreateClientFunc + if createClientFunc != nil { + return createClientFunc(options) + } + return &fasthttp.Client{ + TLSConfig: &tls.Config{InsecureSkipVerify: options.InsecureSkipVerify}, + } +} diff --git a/util/url_utils.go b/util/url_utils.go index 3e8a08d..bc73f7b 100644 --- a/util/url_utils.go +++ b/util/url_utils.go @@ -1,8 +1,10 @@ package util import ( - "github.com/Authing/authing-golang-sdk/v3/constant" + "fmt" "net/url" + + "github.com/Authing/authing-golang-sdk/v3/constant" ) func GetQueryString(queryMap map[string]string) string { @@ -17,5 +19,18 @@ func GetQueryString(queryMap map[string]string) string { queryValue.Add(key, value) } return queryValue.Encode() +} +func GetQueryString2(queryMap map[string]interface{}) string { + if queryMap == nil || len(queryMap) == 0 { + return constant.StringEmpty + } + queryValue := url.Values{} + for key, value := range queryMap { + if value == "" { + continue + } + queryValue.Add(key, fmt.Sprint(value)) + } + return queryValue.Encode() }