/// <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> /// <returns>规范化头信息字符串</returns> private string GetCanonicalizedHeaderString(SdkHttpFullRequestBuilder builder) { var headers = builder.GetHeaders(); var keys = headers.Keys; List <string> keysList = keys.ToList().OrderBy(p => p.ToLower(CultureInfo.GetCultureInfo("en-US"))).ToList(); StringBuilder stringBuilder = new StringBuilder(); foreach (var item in keysList) { if (ShouldExcludeHeaderFromSigning(item)) { continue; } string key = item.ToLower(CultureInfo.GetCultureInfo("en-US")); foreach (var headerValue in headers[item]) { string headerCompactedValue = StringUtils.AppendCompactedString(key); stringBuilder.Append(key).Append(":"); if (headerValue != null) { string headerValueCompactedValue = StringUtils.AppendCompactedString(headerValue); stringBuilder.Append(headerValueCompactedValue); } stringBuilder.Append("\n"); } } return(stringBuilder.ToString()); }
/// <summary> /// 构建Authorization头信息 /// </summary> /// <param name="builder">请求参数封装信息</param> /// <param name="signature">签名信息</param> /// <param name="credentials">证书信息</param> /// <param name="signerParams">签名参数信息</param> /// <returns>http头 Authorization 信息字符串</returns> private string BuildAuthorizationHeader(SdkHttpFullRequestBuilder builder, byte[] signature, ICredentials credentials, SignerRequestParams signerParams) { string signingCredentials = credentials.AccessKeyId() + "/" + signerParams.Scope; string credential = "Credential=" + signingCredentials; string signerHeaders = "SignedHeaders=" + GetSignedHeadersString(builder); string signatureHeader = "Signature=" + StringUtils.ByteToHex(signature, true); return(new StringBuilder().Append(ParameterConstant.JDCLOUD2_SIGNING_ALGORITHM) .Append(" ") .Append(credential) .Append(", ") .Append(signerHeaders) .Append(", ") .Append(signatureHeader) .ToString()); }
/// <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> /// 生成签名头信息字符串 /// </summary> /// <param name="builder">http 请求信息</param> /// <returns>签名头信息字符串</returns> private string GetSignedHeadersString(SdkHttpFullRequestBuilder builder) { var headers = builder.GetHeaders(); var keys = headers.Keys; List <string> keysList = keys.ToList().OrderBy(p => p.ToLower(CultureInfo.GetCultureInfo("en-US"))).ToList(); StringBuilder stringBuilder = new StringBuilder(); foreach (String header in keysList) { if (ShouldExcludeHeaderFromSigning(header)) { continue; } if (stringBuilder.Length > 0) { stringBuilder.Append(";"); } stringBuilder.Append(header.ToLower(CultureInfo.GetCultureInfo("en-US"))); } return(stringBuilder.ToString()); }
/// <summary> /// 计算http content SHA256 hash 校验值 /// </summary> /// <param name="builder">http 请求信息</param> /// <returns>计算后的16进制加密的 content 信息</returns> protected string CalculateContentHash(SdkHttpFullRequestBuilder builder) { try { string content = builder.GetContent(); #if NET35 if (string.IsNullOrEmpty(content) || string.IsNullOrEmpty(content.Trim())) #else if (string.IsNullOrWhiteSpace(content)) #endif { content = string.Empty; } string contentSha256 = StringUtils.ByteToHex(SignHash(content), true); return(contentSha256); } catch (Exception ex) { throw new Exception("get the request content sha256 error", ex); } }
/// <summary> /// 签名的具体实现 /// </summary> /// <param name="builder">http请求信息</param> /// <param name="credentials">证书信息</param> /// <returns>请求后的http 信息</returns> private SdkHttpFullRequestBuilder DoSign(SdkHttpFullRequestBuilder builder, Credentials credentials) { Credentials sanitizedCredentials = SanitizeCredentials(credentials); if (credentials.GetType() == typeof(SessionCredentials)) { AddSessionCredentials(builder, (SessionCredentials)credentials); } //20180627T065220Z //_overrddenDate = new DateTime(2018,6,27,6, 52, 20); SignerRequestParams signerRequestParams = new SignerRequestParams(builder, _overrddenDate, RegionName, ServiceName, ParameterConstant.JDCLOUD2_SIGNING_ALGORITHM); // SignerRequestParams AddHostHeader(ref builder); builder.Header(ParameterConstant.X_JDCLOUD_DATE, signerRequestParams.FormattedSigningDateTime); string contentSha256 = string.Empty; if (builder.GetHeaders() != null && builder.GetHeaders().ContainsKey(ParameterConstant.X_JDCLOUD_CONTENT_SHA256) && builder.GetHeaders()[ParameterConstant.X_JDCLOUD_CONTENT_SHA256] != null && builder.GetHeaders()[ParameterConstant.X_JDCLOUD_CONTENT_SHA256].Count > 0) { contentSha256 = builder.GetHeaders()[ParameterConstant.X_JDCLOUD_CONTENT_SHA256][0]; } else { contentSha256 = CalculateContentHash(builder); } string canonicalRequest = CreateCanonicalRequest(builder, contentSha256); string stringToSign = CreateStringToSign(canonicalRequest, signerRequestParams); byte[] signingKey = deriveSigningKey(credentials, signerRequestParams); byte[] signature = ComputeSignature(stringToSign, signingKey); builder.Header(ParameterConstant.AUTHORIZATION, BuildAuthorizationHeader(builder, signature, credentials, signerRequestParams)); return(builder); }
/// <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); }
/// <summary> /// Adds session credentials to the request given. /// </summary> /// <param name="mutableRequest">request 构建对象</param> /// <param name="credentials">session 认证的 akey 和 skey 信息</param> protected abstract void AddSessionCredentials(SdkHttpFullRequestBuilder mutableRequest, SessionCredentials credentials);
/// <summary> /// 进行签名调用的方法 /// </summary> /// <param name="builder">request 构建对象</param> /// <param name="credentials">认证的akey 和 skey 信息</param> /// <returns>返回签名后的http 请求信息</returns> public abstract SdkHttpFullRequest Sign(SdkHttpFullRequestBuilder builder, Credentials credentials);
/// <summary> /// 添加session 认证信息 /// </summary> /// <param name="mutableRequest">http请求信息</param> /// <param name="credentials">session 认证信息</param> protected override void AddSessionCredentials(SdkHttpFullRequestBuilder mutableRequest, SessionCredentials credentials) { mutableRequest.Header(ParameterConstant.X_JDCLOUD_SECURITY_TOKEN, credentials.SessionToken()); }
/// <summary> /// 进行签名 /// </summary> /// <param name="builder">http 请求使用的信息</param> /// <param name="credentials">请求的认证信息</param> /// <returns>签名后得到的http 请求信息</returns> public override SdkHttpFullRequest Sign(SdkHttpFullRequestBuilder builder, Credentials credentials) { return(DoSign(builder, credentials).Build()); }