You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.7 KiB

  1. package auth
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "golib.gaore.com/GaoreGo/haiwai-common-sdk-go/sdk/requests"
  7. "golib.gaore.com/GaoreGo/haiwai-common-sdk-go/sdk/utils"
  8. "net/http"
  9. "net/url"
  10. "strconv"
  11. "strings"
  12. "time"
  13. )
  14. func signRpcRequest(request requests.AcsRequest, signer Signer) (err error) {
  15. err = completeRpcSignParams(request, signer)
  16. if err != nil {
  17. return
  18. }
  19. if _, isContainsSign := request.GetQueryParams()["sign"]; isContainsSign {
  20. delete(request.GetQueryParams(), "sign")
  21. }
  22. stringToSign := buildRpcStringToSign(request)
  23. request.SetStringToSign(stringToSign)
  24. signature := signer.Sign(stringToSign, "&")
  25. accessKeyForm, err := signer.GetAccessKeyFrom()
  26. if err != nil {
  27. return
  28. }
  29. if accessKeyForm != "" {
  30. request.GetQueryParams()["sign"] = signature
  31. }
  32. debug("GrSdk sign: %s", signature)
  33. debug("GrSdk sign string: %s", stringToSign)
  34. debug("GrSdk sign: \r\n")
  35. return
  36. }
  37. func completeRpcSignParams(request requests.AcsRequest, signer Signer) (err error) {
  38. var accessKeyFrom string
  39. if accessKeyFrom, err = signer.GetAccessKeyFrom(); err != nil {
  40. return
  41. }
  42. if accessKeyFrom != "" {
  43. queryParams := request.GetQueryParams()
  44. queryParams["access_time"] = fmt.Sprintf("%d", time.Now().Unix())
  45. queryParams["access_key"], err = signer.GetAccessKeyId()
  46. queryParams["access_from"] = accessKeyFrom
  47. if err != nil {
  48. return
  49. }
  50. request.GetHeaders()["Gr-Sdk-From"] = accessKeyFrom
  51. }
  52. request.GetHeaders()["Content-type"] = requests.Form
  53. formString := utils.GetUrlFormedMap(request.GetFormParams())
  54. request.SetContent(bytes.NewBufferString(formString).Bytes())
  55. return
  56. }
  57. func buildRpcStringToSign(request requests.AcsRequest) (stringToSign string) {
  58. signParams := make(map[string]string)
  59. for key, value := range request.GetQueryParams() {
  60. signParams[key] = value
  61. }
  62. if strings.ToUpper(request.GetMethod()) == requests.POST {
  63. for key, value := range request.GetFormParams() {
  64. signParams[key] = value
  65. }
  66. }
  67. stringToSign = utils.GetUrlFormedMap(signParams)
  68. stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
  69. stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
  70. stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
  71. stringToSign = url.QueryEscape(stringToSign)
  72. stringToSign = request.GetMethod() + "&%2F&" + stringToSign
  73. return
  74. }
  75. func unsignRpcRequest(request *http.Request, signer Signer) (err error) {
  76. signParams := make(map[string]string)
  77. for key, value := range request.URL.Query() {
  78. signParams[key] = value[0]
  79. }
  80. if strings.ToUpper(request.Method) == requests.POST {
  81. for key, value := range request.Form {
  82. signParams[key] = value[0]
  83. }
  84. }
  85. if accessKey, err := signer.GetAccessKeyId(); err != nil {
  86. return err
  87. } else if accessKey == "" {
  88. return errors.New("access key is not allow empty")
  89. } else if accessKey != signParams["access_key"] {
  90. return errors.New("illegal access key")
  91. }
  92. signValue, ok := signParams["sign"]
  93. if !ok {
  94. return errors.New("sign value is not exists")
  95. } else {
  96. delete(signParams, "sign")
  97. }
  98. stringToSign := utils.GetUrlFormedMap(signParams)
  99. stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
  100. stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
  101. stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
  102. stringToSign = url.QueryEscape(stringToSign)
  103. stringToSign = request.Method + "&%2F&" + stringToSign
  104. debug("GrSdk sign: %s", stringToSign)
  105. if timestamp, err := strconv.ParseInt(signParams["access_time"], 10, 64); err != nil {
  106. return err
  107. } else {
  108. if time.Unix(timestamp, 0).Before(time.Now().Add(-5 * time.Minute)) {
  109. err = errors.New("sign timeout 5 minute")
  110. }
  111. }
  112. if signer.Sign(stringToSign, "&") != signValue {
  113. return errors.New("sign string is not correct")
  114. }
  115. return
  116. }