跨域是由于请求违反了同源策略导致的。而同源策略是所有浏览器都遵循的一种安全原则。也正是因为同源策略的存在决定了浏览器在默认情况下无法对跨域请求的资源做进一步的处理。
为了实现对跨域资源的共享,W3C制定了一种叫做CORS的规范。
CORS规定了浏览器在接收到从资源提供者获取到资源时能够决定是否将此资源分发给资源消费者做进一步的处理。同时规定浏览器需要得到资源提供者的授权后才能将此资源分发给消费者。
注:
- 对于一段js脚本来说,它的源和存储的地址是无关的,而实取决于这个脚本被加载的页面。也就是说,如果在同一个页面中,引用来自两个不同地方的js脚本,它们居于当前页面同源。有一种基于JSONP的跨域资源共享就是基于这种特性。
- html提供的具有src属性的标签,如img、link等。它们也都具有这种跨域加载资源的能力。同源策略对它们是不做限制的。对于这种具有src属性的标签来说,标签的每次加载其实都伴随着针对目标地址的一次Get请求。同源策略以及跨域资源共享在大部分情况下针对的还是ajax请求。
资源提供者需要如何进行资源的授权?并将结果告知给浏览器?
如果浏览器本身支持CORS规范,那么通过浏览器发送的请求都会携带名为Origin的报文头用来表明请求页面所在的站点。资源提供者接收到这么一个请求之后会根据Origin报文头来确定请求的资源需要和谁共享。并通过Access-Control-Allow-Origin响应报文头返回给浏览器。
一般情况下,资源的提供者认可当前的站点。那么,它就会把Origin作为Access-Control-Allow-Origin的值。除了指定具体的源进行针对性的授权,资源提供者还可以把响应报文头直接设置为“*”,这表示对所有的消费者都提供授权。
当浏览器接收到包含资源的响应之后,它会提取响应报文头里Access-Control-Allow-Origin值,如果这个值是一个“*”或则站点列表,那么包含当前请求的站点就意味着资源消费者获得了提供者授予的权限。这种情况下浏览器就会允许程序操作获取的资源。
如果响应报文头Access-Control-Allow-Origin不存在,或则是null。那么客户端的js程序对资源的操作就会被浏览器拒绝。
.NET Core:CORS
.NET Core中的CORS组件就是根据标准的CORS规范实现了资源共享。
示例:
public class demo20
{
public static void Run()
{
var allowedOrigins = new HashSet<string>
{
"www.four.com",
"www.three.com"
};
Host.CreateDefaultBuilder()
.ConfigureWebHostDefaults(builder => builder
.UseUrls("http://*:8080")
.ConfigureServices(collection => collection.AddCors())
// 方式三:直接在服务中添加
//.ConfigureServices(collection => collection.AddCors(options =>
//{
// options.AddDefaultPolicy(
// policyBuilder => policyBuilder.SetIsOriginAllowed(
// origin => allowedOrigins.Contains(new Uri(origin).Host)
// )
// );
//}))
.Configure(app => app
.UsePathBase("/contacts")
// 方式一
//.UseCors(policyBuilder => policyBuilder.WithOrigins("Http:www.one.com:5000", "", ""))
//方式二
//.UseCors(policyBuilder => policyBuilder.SetIsOriginAllowed(origin => allowedOrigins.Contains(new Uri(origin).Host)))
)
)
.Build()
.Run();
}
}