github.com/qiniu/go-sdk/v7@v7.27.0/storagev2/uptoken/uploadtoken.go (about)

     1  package uptoken
     2  
     3  import (
     4  	"context"
     5  	"encoding/base64"
     6  	"encoding/json"
     7  	"errors"
     8  	"strings"
     9  	"sync"
    10  
    11  	"github.com/qiniu/go-sdk/v7/storagev2/credentials"
    12  )
    13  
    14  // ErrInvalidUpToken 非法的上传凭证
    15  var ErrInvalidUpToken = errors.New("invalid upToken")
    16  
    17  type (
    18  	// PutPolicyProvider 获取上传策略接口
    19  	PutPolicyProvider interface {
    20  		GetPutPolicy(context.Context) (PutPolicy, error)
    21  	}
    22  	// AccessKeyProvider 获取 AccessKey 接口
    23  	AccessKeyProvider interface {
    24  		GetAccessKey(context.Context) (string, error)
    25  	}
    26  	// UpTokenProvider 获取上传凭证接口
    27  	UpTokenProvider interface {
    28  		GetUpToken(context.Context) (string, error)
    29  	}
    30  	// Provider 获取上传凭证,AccessKey 和上传策略接口
    31  	Provider interface {
    32  		PutPolicyProvider
    33  		AccessKeyProvider
    34  		UpTokenProvider
    35  	}
    36  	signer struct {
    37  		putPolicy           PutPolicy
    38  		credentialsProvider credentials.CredentialsProvider
    39  		mu                  sync.Mutex
    40  		credentials         *credentials.Credentials
    41  		upToken             string
    42  	}
    43  	parser struct {
    44  		upToken   string
    45  		mu        sync.Mutex
    46  		putPolicy PutPolicy
    47  		accessKey string
    48  		splits    []string
    49  	}
    50  )
    51  
    52  // NewSigner 创建上传凭证签发器
    53  //
    54  // 需要注意的是 NewSigner 仅仅只会通过 credentials.CredentialsProvider 获取一次鉴权参数,之后就会缓存该鉴权参数,不会反复获取
    55  func NewSigner(putPolicy PutPolicy, credentialsProvider credentials.CredentialsProvider) Provider {
    56  	return &signer{putPolicy: putPolicy, credentialsProvider: credentialsProvider}
    57  }
    58  
    59  func (signer *signer) GetPutPolicy(context.Context) (PutPolicy, error) {
    60  	return signer.putPolicy, nil
    61  }
    62  
    63  func (signer *signer) GetAccessKey(ctx context.Context) (string, error) {
    64  	credentials, err := signer.getCredentials(ctx)
    65  	if err != nil {
    66  		return "", err
    67  	}
    68  	return credentials.AccessKey, nil
    69  }
    70  
    71  func (signer *signer) GetUpToken(ctx context.Context) (string, error) {
    72  	signer.mu.Lock()
    73  	if signer.upToken != "" {
    74  		defer signer.mu.Unlock()
    75  		return signer.upToken, nil
    76  	}
    77  	signer.mu.Unlock()
    78  
    79  	credentials, err := signer.getCredentials(ctx)
    80  	if err != nil {
    81  		return "", err
    82  	}
    83  
    84  	putPolicyJson, err := json.Marshal(signer.putPolicy)
    85  	if err != nil {
    86  		return "", err
    87  	}
    88  
    89  	upToken := credentials.SignWithData(putPolicyJson)
    90  
    91  	signer.mu.Lock()
    92  	if signer.upToken == "" {
    93  		signer.upToken = upToken
    94  	}
    95  	signer.mu.Unlock()
    96  
    97  	return signer.upToken, nil
    98  }
    99  
   100  func (signer *signer) getCredentials(ctx context.Context) (*credentials.Credentials, error) {
   101  	signer.mu.Lock()
   102  	if signer.credentials != nil {
   103  		defer signer.mu.Unlock()
   104  		return signer.credentials, nil
   105  	}
   106  	signer.mu.Unlock()
   107  
   108  	var creds *credentials.Credentials
   109  	var err error
   110  	if signer.credentialsProvider != nil {
   111  		creds, err = signer.credentialsProvider.Get(ctx)
   112  		if err != nil {
   113  			return nil, err
   114  		}
   115  	} else if defaultCreds := credentials.Default(); defaultCreds != nil {
   116  		creds = defaultCreds
   117  	}
   118  
   119  	if creds != nil {
   120  		signer.mu.Lock()
   121  		if signer.credentials == nil {
   122  			signer.credentials = creds
   123  		}
   124  		signer.mu.Unlock()
   125  	}
   126  
   127  	return creds, nil
   128  }
   129  
   130  // NewParser 创建上传凭证签发器
   131  func NewParser(upToken string) Provider {
   132  	return &parser{upToken: upToken}
   133  }
   134  
   135  func (parser *parser) GetPutPolicy(ctx context.Context) (PutPolicy, error) {
   136  	parser.mu.Lock()
   137  	if parser.putPolicy != nil {
   138  		defer parser.mu.Unlock()
   139  		return parser.putPolicy, nil
   140  	}
   141  	parser.mu.Unlock()
   142  
   143  	splits, err := parser.getSplits()
   144  	if err != nil {
   145  		return PutPolicy{}, err
   146  	}
   147  
   148  	putPolicyJson, err := base64.URLEncoding.DecodeString(splits[2])
   149  	if err != nil {
   150  		return PutPolicy{}, ErrInvalidUpToken
   151  	}
   152  
   153  	var putPolicy PutPolicy
   154  	if err := json.Unmarshal(putPolicyJson, &putPolicy); err != nil {
   155  		return PutPolicy{}, err
   156  	}
   157  
   158  	parser.mu.Lock()
   159  	if parser.putPolicy == nil {
   160  		parser.putPolicy = putPolicy
   161  	}
   162  	parser.mu.Unlock()
   163  
   164  	return parser.putPolicy, nil
   165  }
   166  
   167  func (parser *parser) GetAccessKey(ctx context.Context) (string, error) {
   168  	parser.mu.Lock()
   169  	if parser.accessKey != "" {
   170  		defer parser.mu.Unlock()
   171  		return parser.accessKey, nil
   172  	}
   173  	parser.mu.Unlock()
   174  
   175  	splits, err := parser.getSplits()
   176  	if err != nil {
   177  		return "", err
   178  	}
   179  
   180  	accessKey := splits[0]
   181  
   182  	parser.mu.Lock()
   183  	if parser.accessKey == "" {
   184  		parser.accessKey = accessKey
   185  	}
   186  	parser.mu.Unlock()
   187  
   188  	return parser.accessKey, nil
   189  }
   190  
   191  func (parser *parser) getSplits() ([]string, error) {
   192  	parser.mu.Lock()
   193  	if len(parser.splits) > 0 {
   194  		defer parser.mu.Unlock()
   195  		return parser.splits, nil
   196  	}
   197  	parser.mu.Unlock()
   198  
   199  	splits := strings.Split(parser.upToken, ":")
   200  	if len(splits) == 5 && splits[0] == "" {
   201  		splits = splits[2:]
   202  	}
   203  	if len(splits) != 3 {
   204  		return nil, ErrInvalidUpToken
   205  	}
   206  
   207  	parser.mu.Lock()
   208  	if len(parser.splits) == 0 {
   209  		parser.splits = splits
   210  	}
   211  	parser.mu.Unlock()
   212  
   213  	return parser.splits, nil
   214  }
   215  
   216  func (parser *parser) GetUpToken(context.Context) (string, error) {
   217  	return parser.upToken, nil
   218  }