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

signer.go 3.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package cdsapi
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/sha256"
  6. "encoding/hex"
  7. "fmt"
  8. "io"
  9. "net/http"
  10. "time"
  11. v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
  12. "github.com/aws/aws-sdk-go-v2/credentials"
  13. )
  14. const (
  15. AuthService = "jcs"
  16. AuthRegion = "any"
  17. )
  18. // 对一个请求进行签名,并将签名信息添加到请求头中。
  19. //
  20. // 会读取请求体计算sha256哈希值。如果hash值已知,可以使用SignWithPayloadHash方法。
  21. func Sign(req *http.Request, accessKey, secretKey string) error {
  22. prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")
  23. cred, err := prod.Retrieve(context.TODO())
  24. if err != nil {
  25. return err
  26. }
  27. payloadHash := ""
  28. if req.Body != nil {
  29. data, err := io.ReadAll(req.Body)
  30. if err != nil {
  31. return err
  32. }
  33. req.Body.Close()
  34. req.Body = io.NopCloser(bytes.NewReader(data))
  35. hasher := sha256.New()
  36. hasher.Write(data)
  37. payloadHash = hex.EncodeToString(hasher.Sum(nil))
  38. } else {
  39. hash := sha256.Sum256([]byte(""))
  40. payloadHash = hex.EncodeToString(hash[:])
  41. }
  42. signer := v4.NewSigner()
  43. err = signer.SignHTTP(context.Background(), cred, req, payloadHash, AuthService, AuthRegion, time.Now())
  44. if err != nil {
  45. return err
  46. }
  47. return nil
  48. }
  49. // 对一个请求进行签名,不计算请求体的哈希,适合上传文件接口。
  50. func SignWithoutBody(req *http.Request, accessKey, secretKey string) error {
  51. prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")
  52. cred, err := prod.Retrieve(context.TODO())
  53. if err != nil {
  54. return err
  55. }
  56. signer := v4.NewSigner()
  57. err = signer.SignHTTP(context.Background(), cred, req, "", AuthService, AuthRegion, time.Now())
  58. if err != nil {
  59. return err
  60. }
  61. return nil
  62. }
  63. // 对一个请求进行签名,签名时使用指定的哈希值作为请求体的哈希值。
  64. //
  65. // 参数payloadHash必须为sha256哈希值的16进制字符串,全小写。
  66. func SignWithPayloadHash(req *http.Request, payloadHash string, accessKey, secretKey string) error {
  67. prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")
  68. cred, err := prod.Retrieve(context.TODO())
  69. if err != nil {
  70. return err
  71. }
  72. signer := v4.NewSigner()
  73. err = signer.SignHTTP(context.Background(), cred, req, payloadHash, AuthService, AuthRegion, time.Now())
  74. if err != nil {
  75. return err
  76. }
  77. return nil
  78. }
  79. // 生成一个带签名的URL。
  80. //
  81. // expiration为签名过期时间,单位为秒。
  82. //
  83. // 签名时不会包含请求体的哈希值。
  84. func Presign(req *http.Request, accessKey, secretKey string, expiration int) (string, error) {
  85. query := req.URL.Query()
  86. query.Add("X-Expires", fmt.Sprintf("%v", expiration))
  87. req.URL.RawQuery = query.Encode()
  88. prod := credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")
  89. cred, err := prod.Retrieve(context.TODO())
  90. if err != nil {
  91. return "", err
  92. }
  93. signer := v4.NewSigner()
  94. signedURL, _, err := signer.PresignHTTP(context.Background(), cred, req, "", AuthService, AuthRegion, time.Now())
  95. return signedURL, err
  96. }