Browse Source

1.增加roa请求,

2.增加阿里(rali) 验签请求加密方式
tags/v1.1.5
liangzy 3 years ago
parent
commit
69c6020214
12 changed files with 458 additions and 8 deletions
  1. +13
    -0
      sdk/auth/credentials/ali_appcode_credential.go
  2. +156
    -0
      sdk/auth/rali_signature_composer.go
  3. +128
    -0
      sdk/auth/roa_signature_composer.go
  4. +14
    -1
      sdk/auth/signer.go
  5. +43
    -0
      sdk/auth/signers/ali_appcode_signer.go
  6. +6
    -0
      sdk/client.go
  7. +8
    -0
      sdk/requests/common_request.go
  8. +13
    -0
      sdk/requests/request.go
  9. +5
    -2
      sdk/requests/rpc_request.go
  10. +61
    -0
      sdk/utils/utils.go
  11. +7
    -1
      services/jedi/client.go
  12. +4
    -4
      services/jedi/send_sms.go

+ 13
- 0
sdk/auth/credentials/ali_appcode_credential.go 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,
}
}

+ 156
- 0
sdk/auth/rali_signature_composer.go 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
}

+ 128
- 0
sdk/auth/roa_signature_composer.go 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
}

+ 14
- 1
sdk/auth/signer.go View File

@@ -24,6 +24,8 @@ func NewSignerWithCredential(credential Credential, commonApi func(request *requ
signer = signers.NewAccessKeySigner(instance.ToAccessKeyCredential())
case *credentials.StdTokenCredential:
signer = signers.NewStsTokenSigner(instance)
case *credentials.AliAppcodeCredential:
signer = signers.NewAliAppcodeSigner(instance)
default:
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) {
switch signer.(type) {
case *signers.AliAppcodeSigner:
err = signRaliRequest(request, signer)
return
}

//TODO 根据rpc和roa两种风格签名,自行选择
err = signRpcRequest(request, signer)
switch request.GetStyle() {
case requests.RPC:
err = signRpcRequest(request, signer)
case requests.ROA:
err = signRoaRequest(request, signer)
}
return
}



+ 43
- 0
sdk/auth/signers/ali_appcode_signer.go 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
}

+ 6
- 0
sdk/client.go View File

@@ -93,6 +93,12 @@ func (client *Client) InitWithAccessKey(accessKeyId, accessKeySecret, accessKeyF
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) {
config := client.InitWithConfig()
credential := &credentials.StdTokenCredential{


+ 8
- 0
sdk/requests/common_request.go View File

@@ -26,3 +26,11 @@ func (request *CommonRequest) BuildQueries() string {
func (request *CommonRequest) GetBodyReader() io.Reader {
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)
}

+ 13
- 0
sdk/requests/request.go View File

@@ -64,7 +64,10 @@ type AcsRequest interface {
GetDomain() string
GetActionName() string
GetAcceptFormat() string
GetAccept() string
GetHeaders() map[string]string
GetStyle() string
InitWithApiInfo(domain, version, urlPath string)

BuildUrl() string
BuildQueries() string
@@ -119,6 +122,16 @@ func (request *baseRequest) GetAcceptFormat() string {
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 {
return request.Headers
}


+ 5
- 2
sdk/requests/rpc_request.go View File

@@ -24,6 +24,10 @@ func (request *RpcRequest) BuildUrl() string {
return url + request.BuildQueries()
}

func (request *RpcRequest) GetStyle() string {
return RPC
}

func (request *RpcRequest) BuildQueries() string {
path := strings.TrimLeft(strings.TrimSpace(request.GetActionName()), "/")
request.queries = "/" + path + "?" + utils.GetUrlFormedMap(request.QueryParams)
@@ -34,12 +38,11 @@ func (request *RpcRequest) GetActionName() string {
return request.actionName
}

func (request *RpcRequest) InitWithApiInfo(domain, version, urlPath string) *RpcRequest {
func (request *RpcRequest) InitWithApiInfo(domain, version, urlPath string) {
request.init()
request.SetDomain(domain)
request.version = version
request.actionName = urlPath
return request
}

func (request *RpcRequest) GetBodyReader() io.Reader {


+ 61
- 0
sdk/utils/utils.go View File

@@ -1,14 +1,63 @@
package utils

import (
"crypto/md5"
"crypto/rand"
"encoding/hex"
"fmt"
"hash"
rand2 "math/rand"
"net/url"
"reflect"
"sort"
"strconv"
"strings"
"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) {
urlEncoder := url.Values{}
for key, value := range source {
@@ -18,6 +67,18 @@ func GetUrlFormedMap(source map[string]string) (urlEncoded string) {
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{}) {
beantype := reflect.TypeOf(bean)
for i := 0; i < beantype.Elem().NumField(); i++ {


+ 7
- 1
services/jedi/client.go View File

@@ -6,7 +6,7 @@ import (
)

const (
HOST = "jedi"
HOST = "jedi.oapi.gaore.com"
VERSION = "2020-08-04"
)

@@ -34,3 +34,9 @@ func NewClientWithAccessKey(accesskey, secrect, source string) (client *Client,
err = client.InitWithAccessKey(accesskey, secrect, source)
return
}

func NewClientWithAliAppcode(accesskey, secrect string) (client *Client, err error) {
client = &Client{}
err = client.InitWithAliAppcode(accesskey, secrect)
return
}

+ 4
- 4
services/jedi/send_sms.go View File

@@ -7,9 +7,9 @@ import (

type SendSmsRequest struct {
*requests.RpcRequest
User string `position:"Query" field:"user" default:"" `
Code string `position:"Query" field:"code" default:"" `
Params string `position:"Query" field:"params" default:"" `
User string `position:"Body" field:"user" default:"" `
Code string `position:"Body" field:"code" default:"" `
Params string `position:"Body" field:"params" default:"" `
ParamsArray []string
}

@@ -28,7 +28,7 @@ func CreateSendSmsRequest() (req *SendSmsRequest) {
RpcRequest: &requests.RpcRequest{},
}
req.InitWithApiInfo(HOST, VERSION, "/api/sms/send")
req.Method = requests.GET
req.Method = requests.POST
return
}



Loading…
Cancel
Save