mod_security (Apache) обрабатывает запрос multipart / form-data в C # - PullRequest
0 голосов
/ 05 июля 2018

Примерно три года на моем сервере запускается php-скрипт. Я использую его для загрузки своих фотографий. Сценарий адресован через программу на C #. Пока все прошло отлично, но за месяц хостер установил mod_security для Apache и больше ничего не работает. Я всегда получаю эту ошибку:

[client 80.187.126.54] ModSecurity: Access denied with code 400 (phase 2).
 Match of "eq 0" against "REQBODY_ERROR" required. 
[file "/etc/httpd/conf.d/mod_security.conf"] [line "16"] [id "200001"] 
[msg "Failed to parse request body."] [data "Multipart parsing error:
 Multipart: Invalid Content-Disposition header (-11): 
 form-data; name=file; filename=20180417_090524_X-H1_4930.jpg; filename*=utf-8''20180417_090524_X-H1_4930.jpg."]
[severity "CRITICAL"] [hostname "myhost.com"] [uri "/manage/api1/api.php"] [unique_id "Wz3bfi6fodp1DjmLF6Jq8AAAABM"]

Вот мой код на c #, который я всегда загружал:

string result = "";

        var requestUri = new Uri(MyHost.API_URL);
        NameValueCollection formData = new NameValueCollection
        {
            {"albumid", album.ID.ToString()}
        };
        var cancellationToken = CancellationToken.None;

        using (var multiPartContent = new MultipartFormDataContent("---------------------------" + DateTime.Now.Ticks.ToString("x")))
        {
            #region Build Request Content
            multiPartContent.Headers.Add("Reqtype", "uploadimage");

            foreach (string key in formData)
            {
                multiPartContent.Add(new StringContent(formData[key]), key);
            }

            FileStream fileStream = new FileStream(mediaItem.LocalPath, FileMode.Open, FileAccess.Read);
            StreamContent streamContent = new StreamContent(fileStream);
            multiPartContent.Add(streamContent, "file", mediaItem.LocalName);
            streamContent.Headers.ContentType = new MediaTypeHeaderValue("image/jpg");

            #endregion

            #region creates HttpRequestMessage object

            HttpRequestMessage httpRequest = new HttpRequestMessage
            {
                Method = HttpMethod.Post,
                RequestUri = requestUri,
                Content = multiPartContent
            };

            #endregion

            #region Send the request and process response
            // Send Request

            HttpResponseMessage httpResponse = null;
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                HttpClient httpClient = new HttpClient
                {
                    Timeout = TimeSpan.FromSeconds(300)
                };

                httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + MyHost.AccessToken);

                httpResponse = httpClient.SendAsync(httpRequest, cancellationToken).Result; //(httpRequest, cancellationToken).ConfigureAwait(false);

                HttpStatusCode statusCode = httpResponse.StatusCode;
                if (statusCode != HttpStatusCode.OK)
                {
                    string errorResponse = httpResponse.Content.ReadAsStringAsync().Result; //ConfigureAwait(false);

                    throw new Exception(errorResponse);
                }
            }
            finally
            {
                if (httpResponse != null)
                {
                    result = httpResponse.Content.ReadAsStringAsync().Result;
                    JsonResponse ReqImg1 = JsonGenerator.GetCommonResponse(result/*MyReq.RespMessage.ResponseString*/);


                    if (ReqImg1.status == "200 OK")
                    {
                        JsonImageListResponse resp = JsonGenerator.GetImageFromJsonResponse(result);
                        mediaItem.link = resp.response.link;
                    }
                    else
                    {
                        //TODO log
                    }
                    httpResponse.Dispose();
                }
            }
            return mediaItem;
            #endregion
        }

В тот момент, когда я понятия не имею, что я могу сделать, чтобы это заработало ....

1 Ответ

0 голосов
/ 15 сентября 2018

Я думаю, что проблема может быть в вашем заголовке здесь:

filename*=utf-8''20180417_090524_X-H1_4930.jpg."

В других сообщениях также упоминается кодировка base_64 ваших изображений.

За исключением того, что они этого не сделают, но вы могли бы попросить вашего хостинг-провайдера отключить это правило в mod_security:

SecRule REQBODY_ERROR "!@eq 0" \
    "id:'...', phase:2,t:none,log,deny,status:400,msg:'Failed to parse request body.',logdata:'%{reqbody_error_msg}',severity:2"

Для моей проблемы я только что удалил mod_security на данный момент, потому что то, на что он отказывается, разрешено соответствующим RFC. Будет больше исследований, когда позволит время. Пока что мои сценарии снова работают.

...