我有一个简单的龙卷风服务器,它有类:
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-OWIN2-20160208103141.mdf;Initial Catalog=aspnet-OWIN2-20160208103141;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<modules>
<remove name="FormsAuthenticationModule" />
</modules>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.AspNet.Identity.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
当发出常规(无CORS)请求时,服务器按预期应答,包括Access-Control-Allow-Origin标头。但是当我发出来自不同域的帖子请求时(使用class BaseHandler(tornado.web.RequestHandler):
def set_default_headers(self):
print "setting headers!!!"
self.set_header("Access-Control-Allow-Origin", "*")
),响应为404并显示错误:“XMLHttpRequest无法加载http://dev-machine:8090/handshake。否'Access-Control-Allow-Origin'标头出现在请求的资源上。因此不允许原点“http://localhost:8090”访问。响应的HTTP状态代码为404.“
你能告诉我是否错过了什么吗? (另一个标题/其他配置/其他任何东西)
答案 0 :(得分:31)
您的代码缺少预检,OPTIONS
请求。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS:
跨域资源共享标准通过添加新HTTP来工作 允许服务器描述原始集合的标头 允许使用Web浏览器读取该信息。另外, 对于可能对用户数据造成副作用的HTTP请求方法(in 特别是,对于GET以外的HTTP方法,或者对于POST使用 某些MIME类型),规范要求浏览器 “预检”请求,从服务器请求支持的方法 使用HTTP OPTIONS请求方法,然后,在“批准”时 服务器,使用实际的HTTP请求发送实际请求 方法。服务器还可以通知客户端是否“凭据” (包括Cookie和HTTP身份验证数据)应与之一起发送 请求。
要实现预检处理程序,只需添加具有相同标题且没有正文的选项处理程序。
class BaseHandler(tornado.web.RequestHandler):
def set_default_headers(self):
print "setting headers!!!"
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
def post(self):
self.write('some post')
def get(self):
self.write('some get')
def options(self):
# no body
self.set_status(204)
self.finish()
修改强>
我已将x-requested-with
标头添加到允许列表中。这里是简单的jquery示例:
$.ajax({
url: "http://some_tornado/api",
type: "POST",
crossDomain: true,
data: 'some_data',
success: function (response) {
alert(response);
},
error: function (xhr, status) {
alert("error");
}
});
关于cors的一些非常好的文章 - http://dev.housetrip.com/2014/04/17/unleash-your-ajax-requests-with-cors/
答案 1 :(得分:7)
kwarunek的回答让我解决了PUT和DELETE请求的问题。唯一的问题是,该解决方案对于使用GET和POST的示例而言过于合适。在这种情况下,行
self.set_header("Access-Control-Allow-Origin", "*")
实际上已经足够了(如果浏览器之前没有阻止CORS)。它与PUT和DELETE请求最相关。在网络级别上发生的事情可能比在GET / POST情况下稍微复杂一些。
“如果请求是”非简单“请求,浏览器首先发送无数据”预检“OPTIONS请求,以验证服务器是否接受请求。使用HTTP时请求不简单除GET或POST之外的动词(例如PUT,DELETE)。“ cf. non-simple requests
class BaseHandler(tornado.web.RequestHandler):
def set_default_headers(self):
print("setting headers!!!")
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
self.set_header('Access-Control-Allow-Methods', ' PUT, DELETE, OPTIONS')
def options(self):
# no body
self.set_status(204)
self.finish()
现在,所有继承自BaseHandler
的处理程序都具备完全支持CORS的能力:
class MyHandler(BaseHandler):
def put(self):
self.write('some post')
def delete(self):
self.write('some get')
答案 2 :(得分:2)
这对我有用。
def set_default_headers(self):
self.set_header("Content-Type", "application/json")
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "content-type")
self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PATCH, PUT')
答案 3 :(得分:1)
即使使用之前的答案,我仍然遇到以下CORS错误:
阻止跨源请求:同源策略禁止读取 远程资源在 http://127.0.0.1:9999/home?message=Input%20to%20API ..(原因:失踪 CORS标头中的令牌“access-control-allow-origin” 来自CORS预检频道的“Access-Control-Allow-Headers”。
解决方案 也允许标题:
class BaseHandler(tornado.web.RequestHandler):
def set_default_headers(self):
print("setting headers!!!")
self.set_header("access-control-allow-origin", "*")
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
self.set_header('Access-Control-Allow-Methods', 'GET, PUT, DELETE, OPTIONS')
# HEADERS!
self.set_header("Access-Control-Allow-Headers", "access-control-allow-origin,authorization,content-type")
def options(self):
# no body
self.set_status(204)
self.finish()