태그 보관물: asp.net-web-api

asp.net-web-api

ASP.NET MVC / WebAPI 응용 프로그램에서 HTTP OPTIONS 동사를 지원하는 방법 please try

MVC 4 / Web API 템플릿으로 시작하는 ASP.NET 웹 응용 프로그램을 설정했습니다. 정말 잘 작동하는 것 같습니다. 제가 아는 문제는 없습니다. Chrome과 Firefox를 사용하여 사이트를 방문했습니다. 나는 Fiddler를 사용하여 테스트했으며 모든 응답이 돈에있는 것 같습니다.

이제이 새로운 웹 API를 사용하기 위해 간단한 Test.aspx를 작성하겠습니다. 스크립트의 관련 부분 :

<script type="text/javascript">
    $(function () {

        $.ajax({
            url: "http://mywebapidomain.com/api/user",
            type: "GET",
            contentType: "json",
            success: function (data) {

                $.each(data, function (index, item) {

                    ....

                    });
                }
                );

            },
            failure: function (result) {
                alert(result.d);
            },

            error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert("An error occurred, please try again. " + textStatus);
            }

        });

    });
</script>

REQUEST 헤더가 생성됩니다.

OPTIONS http://host.mywebapidomain.com/api/user HTTP/1.1
Host: host.mywebapidomain.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Origin: http://mywebapidomain.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: content-type
Connection: keep-alive

그대로 Web API는 405 Method Not Allowed를 반환합니다.

HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 30 Sep 2013 13:28:12 GMT
Content-Length: 96

<Error><Message>The requested resource does not support http method 'OPTIONS'.</Message></Error>

OPTIONS 동사가 기본적으로 Web API 컨트롤러에 연결되어 있지 않다는 것을 이해합니다. 그래서 다음 코드를 UserController.cs에 배치했습니다.

// OPTIONS http-verb handler
public HttpResponseMessage OptionsUser()
{
    var response = new HttpResponseMessage();
    response.StatusCode = HttpStatusCode.OK;
    return response;
}

… 이것은 405 Method Not Allowed 오류를 제거했지만 응답이 완전히 비어 있습니다. 데이터가 반환되지 않습니다.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 30 Sep 2013 12:56:21 GMT
Content-Length: 0

추가 논리가 있어야합니다 … Options 메서드를 올바르게 코딩하는 방법이나 컨트롤러가 코드를 넣을 적절한 위치인지 모르겠습니다. Web API 사이트가 Firefox 또는 Chrome에서 볼 때 제대로 응답하지만 위의 .ajax 호출은 오류가 발생한다는 것이 이상합니다. .ajax 코드에서 “프리 플라이트”검사를 어떻게 처리합니까? 클라이언트 측의 .ajax 로직에서이 문제를 해결해야할까요? 또는 OPTIONS 동사를 처리하지 않아 서버 측에서 문제가되는 경우.

누구든지 도울 수 있습니까? 이것은 매우 일반적인 문제임에 틀림 없으며 여기에서 답변을 받으 셨다면 사과드립니다. 검색했지만 도움이되는 답변을 찾지 못했습니다.


IMHO 업데이트 , 이것은 클라이언트 측 문제이며 위의 Ajax JQuery 코드와 관련이 있습니다. 웹 브라우저에서 mywebapidomain / api / user에 액세스 할 때 Fiddler가 405 오류 헤더를 표시하지 않기 때문에 이렇게 말합니다. 이 문제를 복제 할 수있는 유일한 곳은 JQuery .ajax () 호출입니다. 또한 위의 동일한 Ajax 호출은 서버 (동일한 도메인)에서 실행될 때 제대로 작동합니다.

다른 게시물을 찾았습니다. Prototype AJAX 요청이 GET이 아닌 OPTIONS로 전송되었습니다. 관련된 것처럼 보이는 501 오류가 발생 했지만 성공하지 못한 제안을 수정했습니다. 분명히 JQuery는 Ajax 요청이 도메인 간 (내 것이있는) 경우 OPTIONS 헤더를 트리거하는 두 개의 헤더를 추가하도록 코딩되어 있습니다.

'X-Requested-With': 'XMLHttpRequest',
'X-Prototype-Version': Prototype.Version,

JQuery에서 핵심 코드를 수정하는 것보다 더 나은 솔루션이있을 것 같습니다.

아래 제공된 답변은 이것이 서버 측 문제라고 가정합니다. 아마도, 나는 고객에게 의지하고 호스팅 제공 업체에 전화하는 것이 도움이되지 않을 것입니다.



답변

Daniel A. White가 그의 의견에서 말했듯이 OPTIONS 요청은 교차 도메인 JavaScript 요청의 일부로 클라이언트에 의해 생성 될 가능성이 높습니다. 이것은 CORS (Cross Origin Resource Sharing) 호환 브라우저에 의해 자동으로 수행됩니다. 요청은 CORS에 대해 지원되는 요청 동사 및 헤더를 결정하기 위해 실제 AJAX 요청 전에 만들어진 예비 또는 사전 요청입니다. 서버는 HTTP 동사의 전부 또는 일부에 대해 지원하도록 선택할 수 있습니다.

그림을 완성하기 위해 AJAX 요청에는 JavaScript를 호스팅하는 원본 페이지가 제공되는 위치를 식별하는 추가 “Origin”헤더가 있습니다. 서버는 모든 출처의 요청을 지원하거나 알려진 신뢰할 수있는 출처 세트에 대해서만 지원하도록 선택할 수 있습니다. 출처를 허용하는 것은 CSRF (Cross Site Request Forgery)의 위험을 증가시킬 수 있으므로 보안 위험입니다.

따라서 CORS를 활성화해야합니다.

다음은 ASP.Net Web API에서이 작업을 수행하는 방법을 설명하는 링크입니다.

http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api#enable-cors

여기에 설명 된 구현을 통해 무엇보다도

  • 작업 별, 컨트롤러 별 또는 글로벌 기반의 CORS 지원
  • 지원되는 출처
  • CORS aa 컨트롤러 또는 전역 수준을 활성화 할 때 지원되는 HTTP 동사
  • 서버가 원본 간 요청으로 자격 증명 보내기를 지원하는지 여부

일반적으로이 방법은 잘 작동하지만 특히 모든 도메인에서 원본 간 요청을 허용하는 경우 보안 위험을 인식하고 있는지 확인해야합니다. 이를 허용하기 전에 매우 신중하게 생각하십시오.

CORS를 지원하는 브라우저와 관련하여 Wikipedia는 다음 엔진이 CORS를 지원한다고 말합니다.

  • Gecko 1.9.1 (FireFox 3.5)
  • WebKit (Safari 4, Chrome 3)
  • IE8 및 9에서 부분적으로 지원되는 MSHTML / Trident 6 (IE10)
  • Presto (Opera 12)

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing#Browser_support


답변

Mike Goodwin의 답변은 훌륭하지만 시도했을 때 MVC5 / WebApi 2.1을 겨냥한 것 같습니다. Microsoft.AspNet.WebApi.Cors에 대한 종속성은 내 MVC4 프로젝트에서 잘 작동하지 않았습니다.

MVC4로 WebApi에서 CORS를 활성화하는 가장 간단한 방법은 다음과 같습니다.

모든 것을 허용했습니다. Origin의 API를 제공 할 클라이언트로 제한하는 것이 좋습니다. 모든 것을 허용하는 것은 보안 위험입니다.

Web.config :

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD" />
        <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
      </customHeaders>
    </httpProtocol>
</system.webServer>

BaseApiController.cs :

OPTIONS http 동사를 허용하기 위해 이렇게합니다.

 public class BaseApiController : ApiController
  {
    public HttpResponseMessage Options()
    {
      return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
    }
  }


답변

이를 Application_OnBeginRequest메서드에 추가하고 (이렇게하면 애플리케이션에 대한 CORS 지원이 전역 적으로 활성화 됨) 프리 플라이트 요청을 “처리”합니다.

var res = HttpContext.Current.Response;
var req = HttpContext.Current.Request;
res.AppendHeader("Access-Control-Allow-Origin", req.Headers["Origin"]);
res.AppendHeader("Access-Control-Allow-Credentials", "true");
res.AppendHeader("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");
res.AppendHeader("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");

// ==== Respond to the OPTIONS verb =====
if (req.HttpMethod == "OPTIONS")
{
    res.StatusCode = 200;
    res.End();
}

* 보안 : 이것은 어디에서나 서버로의 ajax 요청을 활성화한다는 점에 유의하십시오 (원하는 경우 쉼표로 구분 된 출처 / URL 목록 만 허용 할 수 있음).

대신 현재 클라이언트 원본을 사용했습니다. *왜냐하면 자격 증명 => Access-Control-Allow-Credentialstrue로 설정하면 크로스 브라우저 세션 관리가 가능하기 때문입니다.

또한 webconfig섹션 에서 삭제 및 배치, 패치 및 옵션 동사를 활성화해야합니다 system.webServer. 그렇지 않으면 IIS에서 차단합니다.

<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

도움이 되었기를 바랍니다


답변

Web API 2 프로젝트에서 동일한 문제가 발생한 후 (여기에 들어갈 가치가없는 이유로 표준 CORS 패키지를 사용할 수 없음) 사용자 지정 DelagatingHandler를 구현하여이 문제를 해결할 수있었습니다.

public class AllowOptionsHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var response = await base.SendAsync(request, cancellationToken);

        if (request.Method == HttpMethod.Options &&
            response.StatusCode == HttpStatusCode.MethodNotAllowed)
        {
            response = new HttpResponseMessage(HttpStatusCode.OK);
        }

        return response;
    }
}

Web API 구성의 경우 :

config.MessageHandlers.Add(new AllowOptionsHandler());

여기에 게시 된 다른 답변과 유사하게 Web.config에서 CORS 헤더가 활성화되어 있습니다.

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <remove name="WebDAVModule" />
  </modules>

  <httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Headers" value="accept, cache-control, content-type, authorization" />
      <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
    </customHeaders>
  </httpProtocol>

  <handlers>
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <remove name="TRACEVerbHandler" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  </handlers>
</system.webServer>

내 프로젝트에는 MVC가 포함되지 않고 Web API 2 만 포함되어 있습니다.


답변

나는 global.asax의 사용자 정의 코드에 의해서만 pre-flight ajax 옵션 요청에 던져진 405 및 404 오류를 극복했습니다.

protected void Application_BeginRequest()
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            //These headers are handling the "pre-flight" OPTIONS call sent by the browser
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
            HttpContext.Current.Response.End();
        }
    }

PS : 모든 것을 허용 할 때 보안 문제 고려 *.

‘Access-Control-Allow-Origin’헤더에 여러 값이 포함되어 있기 때문에 CORS를 비활성화해야했습니다.

web.config에서도 필요했습니다.

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
  <remove name="OPTIONSVerbHandler"/>
  <remove name="TRACEVerbHandler"/>
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>

그리고 app.pool을 통합 모드로 설정해야합니다.


답변

나는 이와 같은 문제가 있었다. 나에게 수정은 jQuery AJAX 호출에서 사용자 정의 컨텐츠 유형을 제거하는 것이 었습니다. 사용자 지정 콘텐츠 유형은 비행 전 요청을 트리거합니다. 나는 이것을 찾았다:

브라우저는 다음 조건이 참인 경우 프리 플라이트 요청을 건너 뛸 수 있습니다.

요청 방법은 GET, HEAD또는 POST,

응용 프로그램이 아닌 다른 요청 헤더를 설정하지 않습니다 Accept, Accept-Language, Content-Language, Content-Type, 또는 Last-Event-ID,

Content-Type헤더 (설정 한 경우) 다음 중 하나입니다 :

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

이 페이지에서 : http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api(“Preflight Requests “아래)


답변

ASP.NET 웹 API 2에서는 CORS 지원이 추가되었습니다. 링크를 확인하십시오 [ http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api ]