【问题标题】:Sending Data to ServiceStack RESTful service, getting 'Access is denied'将数据发送到 ServiceStack RESTful 服务,得到“访问被拒绝”
【发布时间】:2013-09-26 06:20:51
【问题描述】:

我使用 ServiceStack 构建了一个 RESTful 服务,该服务将数据发送到数据库。我在本地测试过,效果很好。当我将它部署到服务器并运行相同的代码(即 jQuery $.ajax 调用)时,我收到“拒绝访问”错误。我在我的 ServiceStack 配置中设置了 CORS,使用插件为explained here。我还在我的 ajax 调用中将 crossDomain 设置为 true。我想不出还有什么办法可以让它工作,老实说,我不确定这个错误是在哪里引发的。我已经通过了 Javascript,它甚至没有到达 ajax 调用的“失败”块,在此之前抛出了错误......我正在使用 IE9 进行测试,如果这是相关的......?

知道会发生什么吗?

这是我的 ServiceStack POST 方法:

    public CitationResponse Post(Citation citation)
    {
        var response = new CitationResponse { Accepted = false };

        if (string.IsNullOrEmpty(citation.ReportNumber))
        {
            response.Accepted = false;
            response.Message = "No data sent to service.  Please enter data in first.";
            return response;
        }

        try
        {
            response.ActivityId = Repository.CreateCitation(citation.ReportNumber, citation.ReportNumber_Prefix, citation.ViolationDateTime, citation.AgencyId, citation.Status);
            response.Accepted = true;
        }
        catch (Exception ex)
        {
            response.Accepted = false;
            response.Message = ex.Message;
            response.RmsException = ex;
        }

        return response;
    }

这是我调用网络服务的 Javascript 函数:

   SendCitationToDb: function(citation, callback) {
        $.ajax({
            type: "POST",
            url: Citations.ServiceUrl + "/citations",
            data: JSON.stringify(citation),
            crossDomain: true,
            contentType: "application/json",
            dataType: "json",
            success: function (data) {
                if (!data.Accepted) {
                    Citations.ShowMessage('Citation not added', 'Citation not added to database.  Error was: ' + data.Message, 'error');
                } else {
                    citation.ActivityId = data.ActivityId;
                    callback(data);
                }
            },
            failure: function(errMsg) {
                Citations.ShowMessage('Citation not added', 'Citation not added to database.  Error was: ' + errMsg.Message, 'error');
            }
        });
    }

感谢您的帮助!

更新: 我刚刚在 Chrome 29 中运行了相同的应用程序,我收到了这些错误(为了安全,替换了真实的 URL):

OPTIONS http://servicedomain.com/citations Origin http://callingdomain.com 是 Access-Control-Allow-Origin 不允许的。

XMLHttpRequest 无法加载 http://servicedomain.com//citations。 Access-Control-Allow-Origin 不允许来源 http://callingdomain.com。

但我明确允许标题中的所有域:

            Plugins.Add(new CorsFeature()); //Enable CORS

            SetConfig(new EndpointHostConfig {
                DebugMode = true, 
                AllowJsonpRequests = true,
                WriteErrorsToResponse = true,
                GlobalResponseHeaders =
                {
                    { "Access-Control-Allow-Origin", "*" },
                    { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }
                }
            });

现在,如果我通过 Chrome 中的 REST Console app 运行相同的服务调用,我会从 ServiceStack 获得有效响应。这是响应标头:

状态码:200
日期:格林威治标准时间 2013 年 9 月 20 日星期五 19:54:26
服务器:Microsoft-IIS/6.0
X-AspNet-版本:4.0.30319
X-Powered-By: ASP.NET, ServiceStack/3.948 Win32NT/.NET
访问控制允许方法:POST、GET、OPTIONS、GET、POST、PUT、DELETE、OPTIONS
内容类型:应用程序/json;字符集=utf-8
访问控制允许来源:*,*
缓存控制:私有
内容长度:58

所以我完全不知道为什么它可以在纯 REST 请求中工作,而不是在应用程序中工作??

更新:

在我花了很多时间尝试我在网上找到的许多不同解决方案之后,我的配置方法现在看起来像这样:

        public override void Configure(Container container)
        {
            SetConfig(new EndpointHostConfig
            {
                DefaultContentType = ContentType.Json,
                ReturnsInnerException = true,
                DebugMode = true, //Show StackTraces for easier debugging (default auto inferred by Debug/Release builds)
                AllowJsonpRequests = true,
                ServiceName = "SSD Citations Web Service",
                WsdlServiceNamespace = "http://www.servicestack.net/types",
                WriteErrorsToResponse = true,
                GlobalResponseHeaders = 
                { 
                    { "Access-Control-Allow-Origin", "*" },
                    { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }
                }
            });

            container.RegisterAutoWired<Citation>();
            container.RegisterAutoWired<Driver>();
            container.RegisterAutoWired<Vehicle>();
            container.RegisterAutoWired<Violations>();

            using (var getAttributes = container.Resolve<AttributesService>())
                getAttributes.Get(new AttributesQuery());

            Plugins.Add(new CorsFeature());
            RequestFilters.Add((httpReq, httpRes, requestDto) =>
            {
                httpRes.AddHeader("Access-Control-Allow-Origin", "*");
                httpRes.AddHeader("Access-Control-Allow-Methods", "POST, GET, DELETE, OPTIONS");
                httpRes.AddHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");

                if (httpReq.HttpMethod == "OPTIONS")
                    httpRes.EndServiceStackRequest(); //   extension method
            });

            Routes
              .Add<Attribute>("/attributes", "GET, OPTIONS")
              .Add<Citation>("/citations", "POST, GET, OPTIONS, DELETE")
              .Add<Driver>("/driver", "POST, OPTIONS")
              .Add<Vehicle>("/vehicle", "POST, OPTIONS")
              .Add<Violations>("/violations", "POST, OPTIONS");

            var config = new AppConfig(new ConfigurationResourceManager());
            container.Register(config);
        }
    }

此时我不知道该怎么做。我已经尝试了一切,但仍然遇到相同的错误。使用 Chrome 中的 REST 控制台,这些方法继续正常工作,这有点令人生气,因为我永远无法让它们工作从网页调用它们。我几乎准备好在 WCF 中重写整个内容,但我真的很想让 ServiceStack 版本正常工作,因为我知道它可以在本地工作!如果有人有任何其他建议我可以尝试,我将非常感谢您的帮助!

更新: 详情见底部评论。我不得不从 IIS 的 HTTP 标头选项卡中删除标头。不知道我什么时候把它们放进去的,但是对于其他可能面临同样问题的人,这里是 IIS 中选项卡的屏幕截图:

【问题讨论】:

  • 注意:CorsFeature 已经将 CORS 标头添加到 Config.GlobalResponseHeaders,因此请从其他任何地方(即 GlobalResponseHeaders 和 RequestFilters 内部)删除它们。如果您仍然有问题,可以在 Chrome 开发工具中发布网络控制台的屏幕截图,并选择错误(红色)请求的详细信息。
  • 对标题的神话建议可能是解决方案。

标签: javascript jquery ajax rest servicestack


【解决方案1】:

在我之前的question中,我和你有同样的问题

您可以阅读#mythz herehere 的非常有用的答案。

我在 AppHost 中使用的代码

          using System.Web;
          using ServiceStack.WebHost.Endpoints.Extensions;  // for  httpExtensions methods  
    //  => after  v.3.9.60,  =>using ServiceStack;

          public override void Configure(Container container)
          {   

                SetConfig(new ServiceStack.WebHost.Endpoints.EndpointHostConfig
                {
                 DefaultContentType = ContentType.Json,
                  ReturnsInnerException = true,
                  WsdlServiceNamespace = "http://www.servicestack.net/types"
                });

             Plugins.Add(new CorsFeature()); 
             this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
             {
                //Handles Request and closes Responses after emitting global HTTP Headers
                   if (httpReq.HttpMethod == "OPTIONS")
                           httpRes.EndServiceStackRequest();  //httpExtensions method
               //  =>after  v.3.9.60, => httpRes.EndRequestWithNoContent(); 
              });

            Routes
             .Add<TestRequest>("/TestAPI/Reservation", "POST, OPTIONS");   // OPTIONS is mandatory for CORS
          }

和像你一样的 JavaScript

  jQuery.support.cors = true;

    function TestRequestCall() {
       var  TestRequest = new Object();                
           TestRequest.Id = 11111;
           TestRequest.City = "New York";



      $.ajax({
          type: 'Post',
          contentType: 'application/json',         
          url: serverIP +'/TestAPI/Reservation',
          data: JSON.stringify( TestRequest ),
          dataType: "json",
          success: function (TestResponse, status, xhr) {

                 if(TestResponse.Accepted)  doSomething();

           },
           error: function (xhr, err) {
              alert(err);
           }
      });
   }

【讨论】:

  • 感谢您的回复。在过去的几天里,我尝试了您的建议以及其他一些建议的修复,但仍然遇到最初问题中提到的相同错误。 IE 显示访问被拒绝,Chrome 显示我的呼叫域“Access-Control-Allow-Origin 不允许。*”对于为什么这不起作用完全感到困惑。我请另一位开发人员看一看,我们在这个星期五和今天都花了几个小时,但仍然没有运气。它在本地工作,在部署时不起作用。如果我直接在 REST 控制台中进行服务调用,它们会起作用,但不是来自 jquery ajax 调用。
  • Eddie,上面的代码在生产环境中工作你试过了吗,作为一个单独的例子?除非我在复制粘贴方面犯了错误,否则它应该可以正常工作。
  • 今天早上我花了一些时间用您的代码构建了一个测试项目,将其部署到同一台服务器上,并且成功了。所以我开始并排比较项目,看看有什么不同。代码中的所有内容看起来都一样。所以最后我远程进入服务器并打开两个站点的属性,发现“HTTP 标头”选项卡中的“自定义 HTTP 标头”列出了相同的标头。我删除了它们,因为我知道 ServiceStack 正在处理这些,并且它起作用了。感谢您和#mythz,感谢您的帮助。我会为其他可能有帮助的人添加屏幕截图。
  • 快乐编程,Eddy
猜你喜欢
  • 1970-01-01
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-27
  • 2012-03-24
  • 2021-07-08
  • 2016-07-23
相关资源
最近更新 更多