7
0

1.增加roa请求,

2.增加阿里(rali) 验签请求加密方式
This commit is contained in:
liangzy 2020-09-23 12:14:23 +08:00
parent 6bfb0c851c
commit 69c6020214
12 changed files with 458 additions and 8 deletions

View File

@ -0,0 +1,13 @@
package credentials
type AliAppcodeCredential struct {
AccessKeyId string `json:"access_key_id" yaml:"access_key_id"`
AccessKeySecret string `json:"access_key_secret" yaml:"access_key_secret"`
}
func NewAliAppcodeCredential(accessKeyId, accessKeySecret string) *AliAppcodeCredential {
return &AliAppcodeCredential{
AccessKeyId: accessKeyId,
AccessKeySecret: accessKeySecret,
}
}

View File

@ -0,0 +1,156 @@
package auth
import (
"bytes"
"errors"
"fmt"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/utils"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
)
func signRaliRequest(request requests.AcsRequest, signer Signer) (err error) {
err = completeRaliSignParams(request, signer)
if err != nil {
return
}
stringToSign := buildRaliStringToSign(request)
request.SetStringToSign(stringToSign)
signature := signer.Sign(stringToSign, "")
request.GetHeaders()["X-Ca-Signature"] = signature
debug("GrSdk sign: %s", signature)
debug("GrSdk sign string: %s", strings.ReplaceAll(stringToSign, "\n", "#"))
debug("GrSdk sign: \r\n")
return
}
func completeRaliSignParams(request requests.AcsRequest, signer Signer) (err error) {
request.GetHeaders()["X-Ca-Timestamp"] = fmt.Sprintf("%d", time.Now().Unix()*1000)
request.GetHeaders()["X-Ca-Signature-Method"] = signer.GetName()
request.GetHeaders()["X-Ca-Nonce"] = utils.GetUUID()
request.GetHeaders()["X-Ca-Key"], err = signer.GetAccessKeyId()
if request.GetMethod() == requests.POST {
request.GetHeaders()["Content-type"] = requests.Form
}
formString := utils.GetUrlFormedMap(request.GetFormParams())
request.SetContent(bytes.NewBufferString(formString).Bytes())
return
}
func buildRaliSignHeader(request requests.AcsRequest) (str1, str2 string) {
headParams := make(map[string]string)
signatureHeaders := make([]string, 0)
for key, val := range request.GetHeaders() {
headParams[key] = val
}
delete(headParams, "X-Ca-Signature")
delete(headParams, "X-Ca-Signature-Headers")
delete(headParams, "Accept")
delete(headParams, "Content-MD5")
delete(headParams, "Content-Type")
delete(headParams, "Date")
for key, _ := range headParams {
signatureHeaders = append(signatureHeaders, key)
}
sort.Strings(signatureHeaders)
for _, key := range signatureHeaders {
str1 += fmt.Sprintf("%s:%s\n", key, headParams[key])
}
return strings.TrimRight(str1, "\n"), strings.Join(signatureHeaders, ",")
}
func buildRaliStringToSign(request requests.AcsRequest) (stringToSign string) {
signParams := make(map[string]string)
for key, value := range request.GetQueryParams() {
signParams[key] = value
}
if strings.ToUpper(request.GetMethod()) == requests.POST {
for key, value := range request.GetFormParams() {
signParams[key] = value
}
}
str1, str2 := buildRaliSignHeader(request)
stringToSign = request.GetMethod() + "\n"
stringToSign += request.GetHeaders()["Accept"] + "\n\n"
stringToSign += request.GetHeaders()["Content-type"] + "\n\n"
stringToSign += str1 + "\n"
stringToSign += request.GetActionName() + "?" + utils.GetUrlByKeySort(signParams)
request.GetHeaders()["X-Ca-Signature-Headers"] = str2
//stringToSign = utils.GetUrlFormedMap(signParams)
//stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
//stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
//stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
//stringToSign = url.QueryEscape(stringToSign)
//stringToSign = request.GetMethod() + "&%2F&" + stringToSign
return
}
func unsignRaliRequest(request *http.Request, signer Signer) (err error) {
signParams := make(map[string]string)
for key, value := range request.URL.Query() {
signParams[key] = value[0]
}
if strings.ToUpper(request.Method) == requests.POST {
for key, value := range request.Form {
signParams[key] = value[0]
}
}
if accessKey, err := signer.GetAccessKeyId(); err != nil {
return err
} else if accessKey == "" {
return errors.New("access key is not allow empty")
} else if accessKey != signParams["access_key"] {
return errors.New("illegal access key")
}
signValue, ok := signParams["sign"]
if !ok {
return errors.New("sign value is not exists")
} else {
delete(signParams, "sign")
}
stringToSign := utils.GetUrlFormedMap(signParams)
stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
stringToSign = url.QueryEscape(stringToSign)
stringToSign = request.Method + "&%2F&" + stringToSign
debug("GrSdk sign: %s", stringToSign)
if timestamp, err := strconv.ParseInt(signParams["access_time"], 10, 64); err != nil {
return err
} else {
if time.Unix(timestamp, 0).Before(time.Now().Add(-5 * time.Minute)) {
err = errors.New("sign timeout 5 minute")
}
}
if signer.Sign(stringToSign, "&") != signValue {
return errors.New("sign string is not correct")
}
return
}

View File

@ -0,0 +1,128 @@
package auth
import (
"bytes"
"errors"
"fmt"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/utils"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
func signRoaRequest(request requests.AcsRequest, signer Signer) (err error) {
err = completeRoaSignParams(request, signer)
if err != nil {
return
}
if _, isContainsSign := request.GetQueryParams()["sign"]; isContainsSign {
delete(request.GetQueryParams(), "sign")
}
stringToSign := buildRoaStringToSign(request)
request.SetStringToSign(stringToSign)
signature := signer.Sign(stringToSign, "&")
request.GetQueryParams()["sign"] = signature
debug("GrSdk sign: %s", signature)
debug("GrSdk sign string: %s", stringToSign)
debug("GrSdk sign: \r\n")
return
}
func completeRoaSignParams(request requests.AcsRequest, signer Signer) (err error) {
var accessKeyFrom string
if accessKeyFrom, err = signer.GetAccessKeyFrom(); err != nil {
return
}
queryParams := request.GetQueryParams()
queryParams["access_time"] = fmt.Sprintf("%d", time.Now().Unix())
queryParams["access_key"], err = signer.GetAccessKeyId()
queryParams["access_from"] = accessKeyFrom
if err != nil {
return
}
if request.GetMethod() == requests.POST {
request.GetHeaders()["Content-type"] = requests.Form
}
request.GetHeaders()["Gr-Sdk-From"] = accessKeyFrom
formString := utils.GetUrlFormedMap(request.GetFormParams())
request.SetContent(bytes.NewBufferString(formString).Bytes())
return
}
func buildRoaStringToSign(request requests.AcsRequest) (stringToSign string) {
signParams := make(map[string]string)
for key, value := range request.GetQueryParams() {
signParams[key] = value
}
if strings.ToUpper(request.GetMethod()) == requests.POST {
for key, value := range request.GetFormParams() {
signParams[key] = value
}
}
stringToSign = utils.GetUrlFormedMap(signParams)
stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
stringToSign = url.QueryEscape(stringToSign)
stringToSign = request.GetMethod() + "&%2F&" + stringToSign
return
}
func unsignRoaRequest(request *http.Request, signer Signer) (err error) {
signParams := make(map[string]string)
for key, value := range request.URL.Query() {
signParams[key] = value[0]
}
if strings.ToUpper(request.Method) == requests.POST {
for key, value := range request.Form {
signParams[key] = value[0]
}
}
if accessKey, err := signer.GetAccessKeyId(); err != nil {
return err
} else if accessKey == "" {
return errors.New("access key is not allow empty")
} else if accessKey != signParams["access_key"] {
return errors.New("illegal access key")
}
signValue, ok := signParams["sign"]
if !ok {
return errors.New("sign value is not exists")
} else {
delete(signParams, "sign")
}
stringToSign := utils.GetUrlFormedMap(signParams)
stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
stringToSign = url.QueryEscape(stringToSign)
stringToSign = request.Method + "&%2F&" + stringToSign
debug("GrSdk sign: %s", stringToSign)
if timestamp, err := strconv.ParseInt(signParams["access_time"], 10, 64); err != nil {
return err
} else {
if time.Unix(timestamp, 0).Before(time.Now().Add(-5 * time.Minute)) {
err = errors.New("sign timeout 5 minute")
}
}
if signer.Sign(stringToSign, "&") != signValue {
return errors.New("sign string is not correct")
}
return
}

View File

@ -24,6 +24,8 @@ func NewSignerWithCredential(credential Credential, commonApi func(request *requ
signer = signers.NewAccessKeySigner(instance.ToAccessKeyCredential()) signer = signers.NewAccessKeySigner(instance.ToAccessKeyCredential())
case *credentials.StdTokenCredential: case *credentials.StdTokenCredential:
signer = signers.NewStsTokenSigner(instance) signer = signers.NewStsTokenSigner(instance)
case *credentials.AliAppcodeCredential:
signer = signers.NewAliAppcodeSigner(instance)
default: default:
err = errors.New("UnsupportedCredentialErrorCode = SDK.UnsupportedCredential") err = errors.New("UnsupportedCredentialErrorCode = SDK.UnsupportedCredential")
} }
@ -31,8 +33,19 @@ func NewSignerWithCredential(credential Credential, commonApi func(request *requ
} }
func Sign(request requests.AcsRequest, signer Signer) (err error) { func Sign(request requests.AcsRequest, signer Signer) (err error) {
switch signer.(type) {
case *signers.AliAppcodeSigner:
err = signRaliRequest(request, signer)
return
}
//TODO 根据rpc和roa两种风格签名自行选择 //TODO 根据rpc和roa两种风格签名自行选择
switch request.GetStyle() {
case requests.RPC:
err = signRpcRequest(request, signer) err = signRpcRequest(request, signer)
case requests.ROA:
err = signRoaRequest(request, signer)
}
return return
} }

View File

@ -0,0 +1,43 @@
package signers
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/credentials"
)
type AliAppcodeSigner struct {
credential *credentials.AliAppcodeCredential
}
func (signer *AliAppcodeSigner) GetName() string {
return "HmacSHA256"
}
func (signer *AliAppcodeSigner) GetAccessKeyId() (string, error) {
return signer.credential.AccessKeyId, nil
}
func (signer *AliAppcodeSigner) GetAccessKeyFrom() (string, error) {
return "", nil
}
func (signer *AliAppcodeSigner) Sign(stringToSign, secretSuffix string) string {
secret := signer.credential.AccessKeySecret + secretSuffix
return ShaHmac256(stringToSign, secret)
}
func NewAliAppcodeSigner(credential *credentials.AliAppcodeCredential) *AliAppcodeSigner {
return &AliAppcodeSigner{
credential: credential,
}
}
func ShaHmac256(source, secret string) string {
key := []byte(secret)
hmac1 := hmac.New(sha256.New, key)
hmac1.Write([]byte(source))
signedString := base64.StdEncoding.EncodeToString(hmac1.Sum(nil))
return signedString
}

View File

@ -93,6 +93,12 @@ func (client *Client) InitWithAccessKey(accessKeyId, accessKeySecret, accessKeyF
return client.InitWithOptions(config, credential) return client.InitWithOptions(config, credential)
} }
func (client *Client) InitWithAliAppcode(accessKeyId, accessKeySecret string) (err error) {
config := client.InitWithConfig()
credential := credentials.NewAliAppcodeCredential(accessKeyId, accessKeySecret)
return client.InitWithOptions(config, credential)
}
func (client *Client) InitWithStsToken(accessKeyId, accessKeySecret, accessKeyFrom string) (err error) { func (client *Client) InitWithStsToken(accessKeyId, accessKeySecret, accessKeyFrom string) (err error) {
config := client.InitWithConfig() config := client.InitWithConfig()
credential := &credentials.StdTokenCredential{ credential := &credentials.StdTokenCredential{

View File

@ -26,3 +26,11 @@ func (request *CommonRequest) BuildQueries() string {
func (request *CommonRequest) GetBodyReader() io.Reader { func (request *CommonRequest) GetBodyReader() io.Reader {
return request.Ontology.GetBodyReader() return request.Ontology.GetBodyReader()
} }
func (request *CommonRequest) GetStyle() string {
return request.Ontology.GetStyle()
}
func (request *CommonRequest) InitWithApiInfo(domain, version, urlPath string) {
request.Ontology.InitWithApiInfo(domain, version, urlPath)
}

View File

@ -64,7 +64,10 @@ type AcsRequest interface {
GetDomain() string GetDomain() string
GetActionName() string GetActionName() string
GetAcceptFormat() string GetAcceptFormat() string
GetAccept() string
GetHeaders() map[string]string GetHeaders() map[string]string
GetStyle() string
InitWithApiInfo(domain, version, urlPath string)
BuildUrl() string BuildUrl() string
BuildQueries() string BuildQueries() string
@ -119,6 +122,16 @@ func (request *baseRequest) GetAcceptFormat() string {
return request.AcceptFormat return request.AcceptFormat
} }
func (request *baseRequest) GetAccept() string {
switch request.GetAcceptFormat() {
case JSON:
return Json
case XML:
return Xml
}
return ""
}
func (request *baseRequest) GetHeaders() map[string]string { func (request *baseRequest) GetHeaders() map[string]string {
return request.Headers return request.Headers
} }

View File

@ -24,6 +24,10 @@ func (request *RpcRequest) BuildUrl() string {
return url + request.BuildQueries() return url + request.BuildQueries()
} }
func (request *RpcRequest) GetStyle() string {
return RPC
}
func (request *RpcRequest) BuildQueries() string { func (request *RpcRequest) BuildQueries() string {
path := strings.TrimLeft(strings.TrimSpace(request.GetActionName()), "/") path := strings.TrimLeft(strings.TrimSpace(request.GetActionName()), "/")
request.queries = "/" + path + "?" + utils.GetUrlFormedMap(request.QueryParams) request.queries = "/" + path + "?" + utils.GetUrlFormedMap(request.QueryParams)
@ -34,12 +38,11 @@ func (request *RpcRequest) GetActionName() string {
return request.actionName return request.actionName
} }
func (request *RpcRequest) InitWithApiInfo(domain, version, urlPath string) *RpcRequest { func (request *RpcRequest) InitWithApiInfo(domain, version, urlPath string) {
request.init() request.init()
request.SetDomain(domain) request.SetDomain(domain)
request.version = version request.version = version
request.actionName = urlPath request.actionName = urlPath
return request
} }
func (request *RpcRequest) GetBodyReader() io.Reader { func (request *RpcRequest) GetBodyReader() io.Reader {

View File

@ -1,14 +1,63 @@
package utils package utils
import ( import (
"crypto/md5"
"crypto/rand"
"encoding/hex"
"fmt" "fmt"
"hash"
rand2 "math/rand"
"net/url" "net/url"
"reflect" "reflect"
"sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
) )
type UUID [16]byte
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func GetUUID() (uuidHex string) {
uuid := NewUUID()
uuidHex = hex.EncodeToString(uuid[:])
return
}
func NewUUID() UUID {
ns := UUID{}
safeRandom(ns[:])
u := newFromHash(md5.New(), ns, RandStringBytes(16))
u[6] = (u[6] & 0x0f) | (byte(2) << 4)
u[8] = (u[8]&(0xff>>2) | (0x02 << 6))
return u
}
func RandStringBytes(n int) string {
b := make([]byte, n)
for i := range b {
b[i] = letterBytes[rand2.Intn(len(letterBytes))]
}
return string(b)
}
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
u := UUID{}
h.Write(ns[:])
h.Write([]byte(name))
copy(u[:], h.Sum(nil))
return u
}
func safeRandom(dest []byte) {
if _, err := rand.Read(dest); err != nil {
panic(err)
}
}
func GetUrlFormedMap(source map[string]string) (urlEncoded string) { func GetUrlFormedMap(source map[string]string) (urlEncoded string) {
urlEncoder := url.Values{} urlEncoder := url.Values{}
for key, value := range source { for key, value := range source {
@ -18,6 +67,18 @@ func GetUrlFormedMap(source map[string]string) (urlEncoded string) {
return return
} }
func GetUrlByKeySort(source map[string]string) (url string) {
keys := make([]string, 0, len(source))
for k := range source {
keys = append(keys, k)
}
sort.Strings(keys)
for _, key := range keys {
url += fmt.Sprintf("%s=%s&", key, source[key])
}
return strings.TrimRight(url, "&")
}
func InitStructWithDefaultTag(bean interface{}) { func InitStructWithDefaultTag(bean interface{}) {
beantype := reflect.TypeOf(bean) beantype := reflect.TypeOf(bean)
for i := 0; i < beantype.Elem().NumField(); i++ { for i := 0; i < beantype.Elem().NumField(); i++ {

View File

@ -6,7 +6,7 @@ import (
) )
const ( const (
HOST = "jedi" HOST = "jedi.oapi.gaore.com"
VERSION = "2020-08-04" VERSION = "2020-08-04"
) )
@ -34,3 +34,9 @@ func NewClientWithAccessKey(accesskey, secrect, source string) (client *Client,
err = client.InitWithAccessKey(accesskey, secrect, source) err = client.InitWithAccessKey(accesskey, secrect, source)
return return
} }
func NewClientWithAliAppcode(accesskey, secrect string) (client *Client, err error) {
client = &Client{}
err = client.InitWithAliAppcode(accesskey, secrect)
return
}

View File

@ -7,9 +7,9 @@ import (
type SendSmsRequest struct { type SendSmsRequest struct {
*requests.RpcRequest *requests.RpcRequest
User string `position:"Query" field:"user" default:"" ` User string `position:"Body" field:"user" default:"" `
Code string `position:"Query" field:"code" default:"" ` Code string `position:"Body" field:"code" default:"" `
Params string `position:"Query" field:"params" default:"" ` Params string `position:"Body" field:"params" default:"" `
ParamsArray []string ParamsArray []string
} }
@ -28,7 +28,7 @@ func CreateSendSmsRequest() (req *SendSmsRequest) {
RpcRequest: &requests.RpcRequest{}, RpcRequest: &requests.RpcRequest{},
} }
req.InitWithApiInfo(HOST, VERSION, "/api/sms/send") req.InitWithApiInfo(HOST, VERSION, "/api/sms/send")
req.Method = requests.GET req.Method = requests.POST
return return
} }