/// <summary> /// 生成预签名头信息 /// </summary> /// <param name="builder">http 请求信息</param> /// <param name="contentSha256">http content 计算过 hmac sha256 的内容信息</param> /// <returns>预签名头信息字符串</returns> private string CreateCanonicalRequest(SdkHttpFullRequestBuilder builder, string contentSha256) { string parameters = builder.GetParameters(); #if NET35 if (!string.IsNullOrEmpty(parameters) && !string.IsNullOrEmpty(parameters.Trim())) #else if (!string.IsNullOrWhiteSpace(parameters)) #endif { if (parameters.StartsWith("?")) { parameters = parameters.Substring(1); } } string path = SdkHttpUtils.AppendUri(builder.GetEndpoint().AbsolutePath, builder.GetResourcePath()); string canonicalRequest = new StringBuilder(builder.GetHttpMethod().ToString().ToUpper()) .Append(ParameterConstant.LINE_SEPARATOR) .Append(GetCanonicalizedResourcePath(path, _doubleUrlEncode)) .Append(ParameterConstant.LINE_SEPARATOR) .Append(parameters) .Append(ParameterConstant.LINE_SEPARATOR) .Append(GetCanonicalizedHeaderString(builder)) .Append(ParameterConstant.LINE_SEPARATOR) .Append(GetSignedHeadersString(builder)) .Append(ParameterConstant.LINE_SEPARATOR) .Append(contentSha256) .ToString(); return(canonicalRequest); }
/// <summary> /// 添加头信息 /// </summary> /// <param name="builder">http请求信息</param> private void AddHostHeader(ref SdkHttpFullRequestBuilder builder) { var endPoint = builder.GetEndpoint(); if (endPoint == null) { throw new ArgumentNullException(" can not get the uri from de SdkHttpFullRequestBuilder , please check the param set "); } StringBuilder hostHeaderBuilder = new StringBuilder(endPoint.Host); if (SdkHttpUtils.IsUsingNonDefaultPort(endPoint)) { hostHeaderBuilder.Append(":").Append(endPoint.Port); } builder.Header(ParameterConstant.HOST, hostHeaderBuilder.ToString()); string contentSha256 = CalculateContentHash(builder); }
/// <summary> /// 进行请求path 转换 /// </summary> /// <param name="path">请求path</param> /// <param name="doubleUrlEncode">是否进行二次编码</param> /// <returns>转换后的path</returns> protected string GetCanonicalizedResourcePath(string path, bool doubleUrlEncode) { #if NET35 if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(path.Trim())) #else if (string.IsNullOrWhiteSpace(path)) #endif { return("/"); } else { string value = doubleUrlEncode ? SdkHttpUtils.UrlEncode(path, true) : path; if (value.StartsWith("/")) { return(value); } else { return($"/{value}"); } } }
/// <summary> /// 进行签名操作 /// </summary> /// <param name="signRequest">http请求信息</param> /// <returns>返回签名后的需要添加的HTTP header 信息</returns> public Dictionary <string, string> Sign(SignRequest signRequest) { Dictionary <string, string> header = new Dictionary <string, string>(); // v4signer JdCloudSigner signer = new JdCloudSigner(); signer.SetRegionName(signRequest.Region); signer.SetServiceName(signRequest.ServiceName); String nonceId = Guid.NewGuid().ToString().ToLower(); //the default http request mothed is `GET` SdkHttpMethod method = SdkHttpMethod.GET; #if NET35 if (!string.IsNullOrEmpty(signRequest.RequestMothed) && !string.IsNullOrEmpty(signRequest.RequestMothed.Trim())) { method = (SdkHttpMethod)Enum.Parse(typeof(SdkHttpMethod), signRequest.RequestMothed.ToUpper()); } #else if (!string.IsNullOrWhiteSpace(signRequest.RequestMothed)) { if (!Enum.TryParse <SdkHttpMethod>(signRequest.RequestMothed.ToUpper(), out method)) { throw new ArgumentException("the http request mothed cast fail , not support ."); } } #endif Uri endPoint = new Uri(signRequest.Host); // Builder #if NET35 string signRequestContent = string.IsNullOrEmpty(signRequest.RequestContent) || string.IsNullOrEmpty(signRequest.RequestContent.Trim()) ? null : signRequest.RequestContent; SdkHttpFullRequestBuilder reqBuilder = DefaultSdkHttpFullRequest.Builder() .HttpMethod(method) .Endpoint(endPoint) .ResourcePath(SdkHttpUtils.UrlEncode(signRequest.Path, true)) .Header(ParameterConstant.X_JDCLOUD_NONCE, nonceId) // .Header(ParameterConstant.CONTENT_TYPE, signRequest.ContentType) .Content(signRequestContent) .QueryParameter(signRequest.QueryParam); #else SdkHttpFullRequestBuilder reqBuilder = DefaultSdkHttpFullRequest.Builder() .HttpMethod(method) .Endpoint(endPoint) .ResourcePath(SdkHttpUtils.UrlEncode(signRequest.Path, true)) .Header(ParameterConstant.X_JDCLOUD_NONCE, nonceId) // .Header(ParameterConstant.CONTENT_TYPE, signRequest.ContentType) .Content(string.IsNullOrWhiteSpace(signRequest.RequestContent) ? null : signRequest.RequestContent) .QueryParameter(signRequest.QueryParam); #endif //对http header 进行处理, 如果 请求为get head delete 默认不放置content-type 签名内不包含content-type if (method != SdkHttpMethod.GET && method != SdkHttpMethod.DELETE && method != SdkHttpMethod.HEAD) { reqBuilder.Header(ParameterConstant.CONTENT_TYPE, signRequest.ContentType); header.Add(ParameterConstant.CONTENT_TYPE, signRequest.ContentType); } // sign SdkHttpFullRequest signed = signer.Sign(reqBuilder, new Credentials(signRequest.Credentials.AccessKeyId(), signRequest.Credentials.SecretAccessKey())); var signedHeader = signed.GetHeaders(); header.Add(ParameterConstant.X_JDCLOUD_NONCE, nonceId); header.Add(ParameterConstant.X_JDCLOUD_DATE, signedHeader[ParameterConstant.X_JDCLOUD_DATE][0]); header.Add(ParameterConstant.AUTHORIZATION, signedHeader[ParameterConstant.AUTHORIZATION][0]); foreach (var item in signedHeader) { if (!header.ContainsKey(item.Key)) { header.Add(item.Key, item.Value[0]); } } return(header); }