ServiceStack,CORS和OPTIONS(No Access-Control-Allow-Origin头) [英] ServiceStack, CORS, and OPTIONS (No Access-Control-Allow-Origin header)

查看:294
本文介绍了ServiceStack,CORS和OPTIONS(No Access-Control-Allow-Origin头)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们在ServiceStack 4中使用了一个休闲API的CORS功能,我们遇到了一些阻碍。

We're hitting a bit of a snag with CORS features of a restful API in ServiceStack 4.

我们想要从cookie会话在cookie中,因此我们在命中API的角度客户端中使用WithCredentials= true创建AJAX调用。

We want to be sneding cookies to the api since the SS session is in the cookies, so we make AJAX calles with "WithCredentials" = true in our angular clients that hit the API.

由于Chrome(至少)像Access-Control-Allow-Origin通配符和WithCredentials一样,我们添加了一个预请求过滤器,以便在Access-Control-Allow-Origin头中回显请求者的源,如下所示:

Since Chrome (at least) doesn't like Access-Control-Allow-Origin wildcards with WithCredentials, we've added a pre-request filter to echo back the requester's origin in the Access-Control-Allow-Origin header like so:

private void ConfigureCors()
            {
                Plugins.Add(new CorsFeature(
                    allowedHeaders: "Content-Type",
                    allowCredentials: true,
                    allowedOrigins: ""));

                PreRequestFilters.Add((httpReq, httpRes) =>
                {
                    string origin = httpReq.Headers.Get("Origin");
                    if (origin != null)
                    {
                        httpRes.AddHeader(HttpHeaders.AllowOrigin, origin);
                    }
                    else
                    {
                        // Add the dev localhost header.
                        httpRes.AddHeader(HttpHeaders.AllowOrigin, "http://localhost:9000");
                    }
                });

                PreRequestFilters.Add((httpReq, httpRes) =>
                {
                    //Handles Request and closes Responses after emitting global HTTP Headers
                    if (httpReq.Verb == "OPTIONS")
                    {
                        httpRes.EndRequest();
                    }
                });
            }

但是,我们在OPTIONS请求上遇到了障碍,在请求结束时不发送Access-Control-Allow-Origin头。这会使Chrome拒绝此调用。

However, we're hitting a snag on OPTIONS requests, because the SS service is not emitting the Access-Control-Allow-Origin header back when the request is ended. This makes Chrome reject the call.

我们尝试在OPTIONS的预请求过滤器中放置一个显式标题,但它仍然不返回OPTIONS调用的ACAO标题:

We tried putting an explicit header inside the pre-request filter for OPTIONS, but it still doesn't return an ACAO header for OPTIONS calls:

 PreRequestFilters.Add((httpReq, httpRes) =>
            {
                //Handles Request and closes Responses after emitting global HTTP Headers
                if (httpReq.Verb == "OPTIONS")
                {
                    httpRes.AddHeader(HttpHeaders.AllowOrigin, "*");
                    httpRes.EndRequest();
                }
            });

看起来这个必须已经被处理,但是我们找不到像这样的东西on StackOverflow。

It seems like this must have been dealt with before, but we couldn't find anything quite like this on StackOverflow.

我们在OPTIONS预请求过滤器上做错了吗?为什么不返回Access-Control-Allow-Origin头?

Are we doing something wrong with the OPTIONS pre-request filter? Why does it not return an Access-Control-Allow-Origin header?

推荐答案

c $ c> allowOriginWhitelist ,例如:

You should add the whitelisted domains in the allowOriginWhitelist, e.g:

Plugins.Add(new CorsFeature(allowedHeaders:"Content-Type",
    allowCredentials:true,
    allowOriginWhitelist:new[]{"http://localhost:9000"}));

v4.0.35中引入了一个问题,其中 PreRequestFilters正在自定义HttpHandlers 中编写,导致 CorsFeature 写出 Access-Control-Allow-Origin 标头两次,导致浏览器拒绝它。此问题现已解决此提交,可从v4.0.36 +现在的< a href =https://github.com/ServiceStack/ServiceStack/wiki/MyGet =nofollow>在MyGet上可用。

There was an issue introduced in v4.0.35 where as PreRequestFilters were being written in Custom HttpHandlers this caused the CorsFeature to write out the Access-Control-Allow-Origin header twice causing browsers to reject it. This has now been resolved in this commit which is available from v4.0.36+ that's now available on MyGet.

最新版本已部署到 http://test.servicestack.net 演示,该演示显示了使用ServiceStack的跨域身份验证在此jsbin中: http://jsbin.com/korijigucu/1/edit

This latest version has been deployed to the http://test.servicestack.net demo which shows cross-domain authentication with ServiceStack in this jsbin: http://jsbin.com/korijigucu/1/edit

<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
  <script>
    var apiBase = "http://test.servicestack.net";
    var app = angular.module('app', []);
    app.run(['$rootScope', '$http', function ($rootScope, $http) {  
      $rootScope.success = "running...";
      $http
         .post(apiBase + '/auth/credentials', 
             { "UserName": "test", "Password": "test" }, 
             { withCredentials: true })
         .success(function (data) {
             $rootScope.success = "Login successful: " + JSON.stringify(data);
         })
         .error(function (data, status, headers, config) {
             $rootScope.error = 'ERR:login';
         });
    }]);    
  </script>
</head>
<body>    
  <div style='color:green'>{{success}}</div>
  <div style='color:red'>{{error}}</div>
</body>
</html>

上面的CorsFeature注册测试项目

Plugins.Add(new CorsFeature(
    allowOriginWhitelist: new[] { 
      "http://localhost", "http://localhost:56500", 
      "http://test.servicestack.net", "http://null.jsbin.com" },
    allowCredentials: true,
    allowedHeaders: "Content-Type, Allow, Authorization"));

这篇关于ServiceStack,CORS和OPTIONS(No Access-Control-Allow-Origin头)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆