예제 #1
0
        /// <summary>
        /// Canonicalizes the HTTP request.
        /// </summary>
        /// <param name="request">A web request.</param>
        /// <param name="accountName">The name of the storage account.</param>
        /// <returns>The canonicalized string for the request.</returns>
        public override string CanonicalizeHttpRequest(HttpWebRequest request, string accountName)
        {
            CanonicalizedString canonicalizedString = new CanonicalizedString(request.Method);

            string httpContentMD5Value = request.Headers[HttpRequestHeader.ContentMd5];

            canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value);

            string contentType = request.ContentType;

            canonicalizedString.AppendCanonicalizedElement(contentType);

            string date = request.Headers[Constants.HeaderConstants.Date];

            if (string.IsNullOrEmpty(date))
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.MissingXmsDateInHeader);
                throw new ArgumentException(errorMessage, "request");
            }

            canonicalizedString.AppendCanonicalizedElement(date);

            canonicalizedString.AppendCanonicalizedElement(GetCanonicalizedResource(request.Address, accountName));

            return(canonicalizedString.ToString());
        }
        /// <summary>
        /// Gets the canonicalized resource string for a Blob or Queue service request under the Shared Key authentication scheme.
        /// </summary>
        /// <param name="address">The resource URI.</param>
        /// <param name="accountName">The name of the storage account.</param>
        /// <returns>The canonicalized resource string.</returns>
        protected static string GetCanonicalizedResourceVersion2(Uri address, string accountName)
        {
            // Resource path
            StringBuilder resourcepath = new StringBuilder("/");

            resourcepath.Append(accountName);

            // Note that AbsolutePath starts with a '/'.
            resourcepath.Append(address.AbsolutePath);

            CanonicalizedString canonicalizedResource = new CanonicalizedString(resourcepath.ToString());

            // query parameters
            NameValueCollection queryVariables         = Utilities.ParseQueryString(address.Query);
            NameValueCollection lowercasedKeyNameValue = new NameValueCollection();

            foreach (string key in queryVariables.Keys)
            {
                // sort the value and organize it as comma separated values
                object[] values = queryVariables.GetValues(key);

                ArrayList sortedValues = new ArrayList(values);
                sortedValues.Sort();

                StringBuilder stringValue = new StringBuilder();

                foreach (object value in sortedValues)
                {
                    if (stringValue.Length > 0)
                    {
                        stringValue.Append(",");
                    }

                    stringValue.Append(value.ToString());
                }

                // key turns out to be null for ?a&b&c&d
                lowercasedKeyNameValue.Add(key == null ? key : key.ToLowerInvariant(), stringValue.ToString());
            }

            ArrayList sortedKeys = new ArrayList(lowercasedKeyNameValue.AllKeys);

            sortedKeys.Sort();

            foreach (string key in sortedKeys)
            {
                StringBuilder queryParamString = new StringBuilder(string.Empty);

                queryParamString.Append(key);
                queryParamString.Append(":");
                queryParamString.Append(lowercasedKeyNameValue[key]);

                canonicalizedResource.AppendCanonicalizedElement(queryParamString.ToString());
            }

            return(canonicalizedResource.Value);
        }
        protected static string CanonicalizeHttpRequest(
            Uri address,
            string accountName,
            string method,
            string contentType,
            string date,
            NameValueCollection headers)
        {
            // The first element should be the Method of the request.
            // I.e. GET, POST, PUT, or HEAD.
            CanonicalizedString canonicalizedString = new CanonicalizedString(method);

            // The second element should be the MD5 value.
            // This is optional and may be empty.
            string httpContentMD5Value = string.Empty;

            // First extract all the content MD5 values from the header.
            ArrayList httpContentMD5Values = GetHeaderValues(headers, "Content-MD5");

            // If we only have one, then set it to the value we want to append to the canonicalized string.
            if (httpContentMD5Values.Count == 1)
            {
                httpContentMD5Value = (string)httpContentMD5Values[0];
            }

            canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value);

            // The third element should be the content type.
            canonicalizedString.AppendCanonicalizedElement(contentType);

            // The fourth element should be the request date.
            // See if there's an storage date header.
            // If there's one, then don't use the date header.
            ArrayList httpStorageDateValues = GetHeaderValues(headers, Constants.HeaderConstants.Date);

            if (httpStorageDateValues.Count > 0)
            {
                date = null;
            }

            canonicalizedString.AppendCanonicalizedElement(date);

            AddCanonicalizedHeaders(headers, canonicalizedString);

            AddCanonicalizedResource(address, accountName, canonicalizedString);

            return(canonicalizedString.Value);
        }
        protected static string CanonicalizeHttpRequest(
            Uri address,
            string accountName,
            string method,
            string contentType,
            string date,
            NameValueCollection headers)
        {
            // The first element should be the Method of the request.
            // I.e. GET, POST, PUT, or HEAD.
            CanonicalizedString canonicalizedString = new CanonicalizedString(method);

            // The second element should be the MD5 value.
            // This is optional and may be empty.
            string httpContentMD5Value = string.Empty;

            // First extract all the content MD5 values from the header.
            ArrayList httpContentMD5Values = GetHeaderValues(headers, "Content-MD5");

            // If we only have one, then set it to the value we want to append to the canonicalized string.
            if (httpContentMD5Values.Count == 1)
            {
                httpContentMD5Value = (string)httpContentMD5Values[0];
            }

            canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value);

            // The third element should be the content type.
            canonicalizedString.AppendCanonicalizedElement(contentType);

            // The fourth element should be the request date.
            // See if there's an storage date header.
            // If there's one, then don't use the date header.
            ArrayList httpStorageDateValues = GetHeaderValues(headers, Constants.HeaderConstants.Date);
            if (httpStorageDateValues.Count > 0)
            {
                date = null;
            }

            canonicalizedString.AppendCanonicalizedElement(date);

            AddCanonicalizedHeaders(headers, canonicalizedString);

            AddCanonicalizedResource(address, accountName, canonicalizedString);

            return canonicalizedString.Value;
        }
        /// <summary>
        /// Add x-ms- prefixed headers in a fixed order.
        /// </summary>
        /// <param name="headers">The headers.</param>
        /// <param name="canonicalizedString">The canonicalized string.</param>
        private static void AddCanonicalizedHeaders(NameValueCollection headers, CanonicalizedString canonicalizedString)
        {
            // Look for header names that start with HeaderNames.PrefixForStorageHeader
            // Then sort them in case-insensitive manner.
            ArrayList httpStorageHeaderNameArray = new ArrayList();

            foreach (string key in headers.Keys)
            {
                if (key.ToLowerInvariant().StartsWith(Constants.HeaderConstants.PrefixForStorageHeader, StringComparison.Ordinal))
                {
                    httpStorageHeaderNameArray.Add(key.ToLowerInvariant());
                }
            }

            httpStorageHeaderNameArray.Sort();

            // Now go through each header's values in the sorted order and append them to the canonicalized string.
            foreach (string key in httpStorageHeaderNameArray)
            {
                StringBuilder canonicalizedElement = new StringBuilder(key);
                string        delimiter            = ":";
                ArrayList     values = GetHeaderValues(headers, key);

                // Go through values, unfold them, and then append them to the canonicalized element string.
                foreach (string value in values)
                {
                    // Unfolding is simply removal of CRLF.
                    string unfoldedValue = value.Replace("\r\n", string.Empty);

                    // Append it to the canonicalized element string.
                    canonicalizedElement.Append(delimiter);
                    canonicalizedElement.Append(unfoldedValue);
                    delimiter = ",";
                }

                // Now, add this canonicalized element to the canonicalized header string.
                canonicalizedString.AppendCanonicalizedElement(canonicalizedElement.ToString());
            }
        }
        /// <summary>
        /// Constructs a canonicalized string from the request's headers that will be used to construct the signature
        /// string for signing a Blob or Queue service request under the Shared Key Lite authentication scheme.
        /// </summary>
        /// <param name="address">The request URI.</param>
        /// <param name="accountName">The storage account name.</param>
        /// <param name="method">The verb to be used for the HTTP request.</param>
        /// <param name="contentType">The content type of the HTTP request.</param>
        /// <param name="contentLength">The length of the HTTP request, in bytes.</param>
        /// <param name="date">The date/time specification for the HTTP request.</param>
        /// <param name="headers">A collection of additional headers specified on the HTTP request.</param>
        /// <returns>A canonicalized string.</returns>
        protected static string CanonicalizeHttpRequestVersion2(
            Uri address,
            string accountName,
            string method,
            string contentType,
            long contentLength,
            string date,
            NameValueCollection headers)
        {
            // The first element should be the Method of the request.
            // I.e. GET, POST, PUT, or HEAD.
            CanonicalizedString canonicalizedString = new CanonicalizedString(method);

            // The next elements are
            // If any element is missing it may be empty.
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Encoding"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Language"));
            canonicalizedString.AppendCanonicalizedElement(contentLength == -1 ? String.Empty : contentLength.ToString());
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-MD5"));
            canonicalizedString.AppendCanonicalizedElement(contentType);

            // If x-ms-date header exists, Date should be empty string
            canonicalizedString.AppendCanonicalizedElement(
                GetStandardHeaderValue(headers, Constants.HeaderConstants.Date) != string.Empty
                ? string.Empty : GetStandardHeaderValue(headers, "Date"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Modified-Since"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Match"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-None-Match"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Unmodified-Since"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Range"));

            AddCanonicalizedHeaders(headers, canonicalizedString);

            AddCanonicalizedResourceVer2(address, accountName, canonicalizedString);

            return(canonicalizedString.Value);
        }
        /// <summary>
        /// Canonicalizes the HTTP request.
        /// </summary>
        /// <param name="request">A web request.</param>
        /// <param name="accountName">The name of the storage account.</param>
        /// <returns>The canonicalized string for the request.</returns>
        public override string CanonicalizeHttpRequest(HttpWebRequest request, string accountName)
        {
            CanonicalizedString canonicalizedString = new CanonicalizedString(request.Method);

            string httpContentMD5Value = request.Headers[HttpRequestHeader.ContentMd5];

            canonicalizedString.AppendCanonicalizedElement(httpContentMD5Value);

            string contentType = request.ContentType;
            canonicalizedString.AppendCanonicalizedElement(contentType);

            string date = request.Headers[Constants.HeaderConstants.Date];
            if (string.IsNullOrEmpty(date))
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.MissingXmsDateInHeader);
                throw new ArgumentException(errorMessage, "request");
            }

            canonicalizedString.AppendCanonicalizedElement(date);

            canonicalizedString.AppendCanonicalizedElement(GetCanonicalizedResource(request.Address, accountName));

            return canonicalizedString.ToString();
        }
        /// <summary>
        /// Add the resource name.
        /// </summary>
        /// <param name="address">The address.</param>
        /// <param name="accountName">Name of the account.</param>
        /// <param name="canonicalizedString">The canonicalized string.</param>
        private static void AddCanonicalizedResource(Uri address, string accountName, CanonicalizedString canonicalizedString)
        {
            // Now we append the canonicalized resource element.
            string canonicalizedResource = GetCanonicalizedResource(address, accountName);

            canonicalizedString.AppendCanonicalizedElement(canonicalizedResource);
        }
        /// <summary>
        /// Add x-ms- prefixed headers in a fixed order.
        /// </summary>
        /// <param name="headers">The headers.</param>
        /// <param name="canonicalizedString">The canonicalized string.</param>
        private static void AddCanonicalizedHeaders(NameValueCollection headers, CanonicalizedString canonicalizedString)
        {
            // Look for header names that start with HeaderNames.PrefixForStorageHeader
            // Then sort them in case-insensitive manner.
            ArrayList httpStorageHeaderNameArray = new ArrayList();

            foreach (string key in headers.Keys)
            {
                if (key.ToLowerInvariant().StartsWith(Constants.HeaderConstants.PrefixForStorageHeader, StringComparison.Ordinal))
                {
                    httpStorageHeaderNameArray.Add(key.ToLowerInvariant());
                }
            }

            httpStorageHeaderNameArray.Sort();

            // Now go through each header's values in the sorted order and append them to the canonicalized string.
            foreach (string key in httpStorageHeaderNameArray)
            {
                StringBuilder canonicalizedElement = new StringBuilder(key);
                string delimiter = ":";
                ArrayList values = GetHeaderValues(headers, key);

                // Go through values, unfold them, and then append them to the canonicalized element string.
                foreach (string value in values)
                {
                    // Unfolding is simply removal of CRLF.
                    string unfoldedValue = value.Replace("\r\n", string.Empty);

                    // Append it to the canonicalized element string.
                    canonicalizedElement.Append(delimiter);
                    canonicalizedElement.Append(unfoldedValue);
                    delimiter = ",";
                }

                // Now, add this canonicalized element to the canonicalized header string.
                canonicalizedString.AppendCanonicalizedElement(canonicalizedElement.ToString());
            }
        }
 /// <summary>
 /// Add the resource name.
 /// </summary>
 /// <param name="address">The address.</param>
 /// <param name="accountName">Name of the account.</param>
 /// <param name="canonicalizedString">The canonicalized string.</param>
 private static void AddCanonicalizedResource(Uri address, string accountName, CanonicalizedString canonicalizedString)
 {
     // Now we append the canonicalized resource element.
     string canonicalizedResource = GetCanonicalizedResource(address, accountName);
     canonicalizedString.AppendCanonicalizedElement(canonicalizedResource);
 }
        /// <summary>
        /// Gets the canonicalized resource string for a Blob or Queue service request under the Shared Key authentication scheme.
        /// </summary>
        /// <param name="address">The resource URI.</param>
        /// <param name="accountName">The name of the storage account.</param>
        /// <returns>The canonicalized resource string.</returns>
        protected static string GetCanonicalizedResourceVersion2(Uri address, string accountName)
        {
            // Resource path
            StringBuilder resourcepath = new StringBuilder("/");
            resourcepath.Append(accountName);

            // Note that AbsolutePath starts with a '/'.
            resourcepath.Append(address.AbsolutePath);

            CanonicalizedString canonicalizedResource = new CanonicalizedString(resourcepath.ToString());

            // query parameters
            NameValueCollection queryVariables = HttpUtility.ParseQueryString(address.Query);
            NameValueCollection lowercasedKeyNameValue = new NameValueCollection();

            foreach (string key in queryVariables.Keys)
            {
                // sort the value and organize it as comma separated values
                object[] values = queryVariables.GetValues(key);

                ArrayList sortedValues = new ArrayList(values);
                sortedValues.Sort();

                StringBuilder stringValue = new StringBuilder();

                foreach (object value in sortedValues)
                {
                    if (stringValue.Length > 0)
                    {
                        stringValue.Append(",");
                    }

                    stringValue.Append(value.ToString());
                }

                // key turns out to be null for ?a&b&c&d
                lowercasedKeyNameValue.Add(key == null ? key : key.ToLowerInvariant(), stringValue.ToString());
            }

            ArrayList sortedKeys = new ArrayList(lowercasedKeyNameValue.AllKeys);

            sortedKeys.Sort();

            foreach (string key in sortedKeys)
            {
                StringBuilder queryParamString = new StringBuilder(string.Empty);

                queryParamString.Append(key);
                queryParamString.Append(":");
                queryParamString.Append(lowercasedKeyNameValue[key]);

                canonicalizedResource.AppendCanonicalizedElement(queryParamString.ToString());
            }

            return canonicalizedResource.Value;
        }
        /// <summary>
        /// Constructs a canonicalized string from the request's headers that will be used to construct the signature
        /// string for signing a Blob or Queue service request under the Shared Key Lite authentication scheme.
        /// </summary>
        /// <param name="address">The request URI.</param>
        /// <param name="accountName">The storage account name.</param>
        /// <param name="method">The verb to be used for the HTTP request.</param>
        /// <param name="contentType">The content type of the HTTP request.</param>
        /// <param name="contentLength">The length of the HTTP request, in bytes.</param>
        /// <param name="date">The date/time specification for the HTTP request.</param>
        /// <param name="headers">A collection of additional headers specified on the HTTP request.</param>
        /// <returns>A canonicalized string.</returns>
        protected static string CanonicalizeHttpRequestVersion2(
            Uri address,
            string accountName,
            string method,
            string contentType,
            long contentLength,
            string date,
            NameValueCollection headers)
        {
            // The first element should be the Method of the request.
            // I.e. GET, POST, PUT, or HEAD.
            CanonicalizedString canonicalizedString = new CanonicalizedString(method);

            // The next elements are 
            // If any element is missing it may be empty.
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Encoding"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-Language"));
            canonicalizedString.AppendCanonicalizedElement(contentLength == -1 ? String.Empty : contentLength.ToString());
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Content-MD5"));
            canonicalizedString.AppendCanonicalizedElement(contentType);

            // If x-ms-date header exists, Date should be empty string
            canonicalizedString.AppendCanonicalizedElement(
                GetStandardHeaderValue(headers, Constants.HeaderConstants.Date) != string.Empty 
                ? string.Empty : GetStandardHeaderValue(headers, "Date"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Modified-Since"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Match"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-None-Match"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "If-Unmodified-Since"));
            canonicalizedString.AppendCanonicalizedElement(GetStandardHeaderValue(headers, "Range"));

            AddCanonicalizedHeaders(headers, canonicalizedString);

            AddCanonicalizedResourceVer2(address, accountName, canonicalizedString);

            return canonicalizedString.Value;
        }