CORS 全稱"跨域資源共用"(Cross-origin resource sharing)。 跨域就是不同域之間進行數據訪問,比如 a.sample.com 訪問 b.sample.com 中的數據,我們如果不做任何處理的話,就會出現下麵的錯誤: XMLHttpRequest cannot loa ...
CORS 全稱"跨域資源共用"(Cross-origin resource sharing)。
跨域就是不同域之間進行數據訪問,比如 a.sample.com 訪問 b.sample.com 中的數據,我們如果不做任何處理的話,就會出現下麵的錯誤:
XMLHttpRequest cannot load b.sample.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'a.sample.com' is therefore not allowed access. The response had HTTP status code 404.
請求和響應信息:
Response Headers
Content-Type:text/html; charset=utf-8
Server:Microsoft-IIS/10.0
X-Powered-By:ASP.NET
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Content-Length:32384
Host:b.sample.com
Origin:a.sample.com
當請求發起後,Host 會獲取 Origin,然後進行判斷是否同意這個請求,判斷的標準就是 Access-Control-Allow-Origin,如果 Host 伺服器指定了 Origin 的配置,那麼在響應頭就會有:
Access-Control-Allow-Origin:a.sample.com
相關的 Access-Control-*:
- Access-Control-Allow-Origin:指定請求頭中 Origin 是否被訪問,如果值為 *,則表示可以讓任何 Origin 訪問。
- Access-Control-Request-Method:允許的 HTTP 請求方法,常用 Get、Post、Put 等,如果值為 *,則表示允許所有的 HTTP 請求方法訪問。
- Access-Control-Expose-Headers:客戶端預設可以從伺服器獲取響應頭中的 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma 欄位信息,如果需要額外獲取其它 header 欄位信息,則需要在服務端進行配置。
Access-Control-Request-Headers:允許客戶端向伺服器發送的額外請求頭信息,和上面的 Access-Control-Expose-Headers 比較相似,但方向是相反的,一般會用在添加自定義 header 的時候,比如 X-Param 等等。 - Access-Control-Allow-Credentials:如果值為 true,則表示服務端可以接受客戶端發送的 Cookie 信息,但客戶端請求中需要同時設置
withCredentials = true;
。 - Access-Control-Max-Age:請求檢查的緩存時間,即在一段時間內,客戶端向伺服器發送請求,不需要再進行檢查 Origin 的配置,而是直接進行請求訪問,當然伺服器更改配置後除外。
以上是 CORS 的基本相關信息,我們在 ASP.NET MVC 應用程式開發中,需要手動配置 CORS:
public class AllowCorsAttribute : ActionFilterAttribute
{
private string[] _domains;
public AllowCorsAttribute(params string[] domains)
{
_domains = domains;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var context = filterContext.RequestContext.HttpContext;
if (context.Request.UrlReferrer != null)
{
var host = context.Request.UrlReferrer?.Host;
if (host != null && _domains.Contains(host))
{
context.Response.AddHeader("Access-Control-Allow-Origin", $"http://{host}");
}
}
else
{
context.Response.AddHeader("Access-Control-Allow-Origin", "*");
}
context.Response.AddHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS, POST, PUT");
context.Response.AddHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
base.OnActionExecuting(filterContext);
}
}
上面代碼就是截獲每次 Action 請求,手動向請求上下文中增加相應頭的配置,以達到 CORS 的目的,Action 配置:
[AllowCors("a.sample.com", "c.sample.com")]
public ActionResult Index()
{
return View();
}
而在 ASP.NET WebAPI 項目中配置 CORS,就不需要上面那麼複雜了,我們只需要安裝:
Install-Package Microsoft.AspNet.WebApi.Cors
然後配置啟用 CORS:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
最後在對應的 Action 上面添加 CORS 配置就行了:
[EnableCors(origins: "http://a.sample.com", headers: "*", methods: "get,post", SupportsCredentials = true)]
public ActionResult Index()
{
return View();
}
在 ASP.NET Core 的 CORS 配置和上面差不多,配置方法:
ConfigureServices 中添加配置:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddCors(options => options.AddPolicy("CorsSample",
p => p.WithOrigins("http://a.example.com", "http://c.example.com").AllowAnyMethod().AllowAnyHeader()));
}
Configure 中啟用配置:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
app.UseCors("CorsSample");
}
Action 啟用對應的 CORS,不啟用使用[DisableCors]
。
[EnableCors("CorsSample")]
public ActionResult Index()
{
return View();
}
當然 CORS 在 ASP.NET Core 的使用不僅於此,你也可以進行自定義,具體查看最後的參考資料。
跨域除了 CORS,還有其它的解決方式:
- JSONP:通過在文檔中嵌入一個
<script>
標記來從另一個域中返回數據,所以只支持 GET 請求,但使用比較簡單,資料:ASP.NET Web API 配置 JSONP - document.domain:JS 配置代碼
document.domain = ‘sample.com’;
,設置完之後,同域之間就可以 JS 互相訪問了,但存在一些隱患,比如一個站點被 JS 註入了,那麼就會牽扯到其它站點,資料:ASP.NET 頁面禁止被 iframe 框架引用
參考資料:
- CORS 簡介
- 跨域資源共用 CORS 詳解
- Enabling Cross-Origin Requests in ASP.NET Web API 2
- Enabling Cross-Origin Requests (CORS)
參考頁面:http://qingqingquege.cnblogs.com/p/5933752.html