一,我们看看什么是跨域
我们可以理解页面发起当一个请求 url 的协议、域名、端口三者之间任意一个与当前页面 url 不同即为跨域。那为什么会出现跨域问题呢?
二,我们先理解跨域的结果是怎样的
如下图结果:
而浏览器提示错误,如下图
由上图我们可以得出结论,其实服务器是返回成功的200,跨域的结果其实是浏览器限制了你的请求
三,那为什么浏览器会限制呢?
由于浏览器的同源策略限制,同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的 javascript 脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
四,那在.net core我们怎么解决跨域问题呢,这个时候我们的cors就出场了,我们看下微软官方文档看下cors的解释
五,看下我们的代码实现三种类型
1》跨源(cross-origin)不带请求证书(Credentials)
js方法如下
$("#btn1").click(function () { //alert(11); $.ajax({ url: 'http://localhost:8000/Home/Get', type: 'Get', success: function (res) { alert(res.name); } }); })
请求结果如下
这个*号是AllowAnyOrigin,设置返回的,返回是允许所有源的意思,如下代码
#region 普通的跨域验证,不带请求中的证书 app.UseCors(builder => { builder.AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod() .SetPreflightMaxAge(TimeSpan.FromSeconds(2000000)); }); #endregion
2》跨源(cross-origin)带请求证书(Credentials)
$("#btn2").click(function () { //alert(11); $.ajax({ url: 'http://localhost:8000/Home/Get', type: 'Get', xhrFields: { withCredentials: true }, crossDomain: true, success: function (res) { alert(res.name); } }); })
我们使用第二种请求方式,而这个时候如果我们开启了,却没有改后端配值,我们发起请求发现。回报如下跨域:Access to XMLHttpRequest at 'http://localhost:8000/Home/Get' from origin 'http://localhost:5000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
这个是什么原因导致的呢?我们看看ajax请求,因为我们使用了 withCredentials: true,而恰恰这个使用是不允许AllowAnyOrigin()的,意思就是不允许返回的Access-Control-Allow-Origin:*,那我们的处理方式如下
我们看看的配置,如下代码,我们必须开启AllowCredentials,同时去掉AllowAnyOrigin,这两个
#region 跨源(cross-origin)请求中的证书(Credentials) 不带自定义参数 ////当在ajax设置了withCredentials: true,就是要带域名的cookie,同时这里是不允许返回Access - Control - Allow - Origin: *这个带星号的,这个时候,我们就要设置允许的参数了 app.UseCors(builder => { builder.SetIsOriginAllowed(_ => true) .AllowCredentials(); }); #endregion
这个时候我们看看请求结果到底有什么区别,如下图
发现我们的请求head多了了Access-Control-Allow-Credentials:true和带了cookie
3》跨源(cross-origin)带请求证书(Credentials)+自定义head参数
如果我们在请求头加自定义参数,我们这个时候又会提示跨域,如下js方法如下
$("#btn3").click(function () { //alert(11); $.ajax({ url: 'http://localhost:8000/Home/Get', type: 'Get', headers: { 'content-type': 'application/json;charset=UTF-8', 'test': "123", 'authorization': '456' }, xhrFields: { withCredentials: true }, crossDomain: true, success: function (res) { alert(res.name); } }); })
如下图错误:Access to XMLHttpRequest at 'http://localhost:8000/Home/Get' from origin 'http://localhost:5000' has been blocked by CORS policy: Request header field test is not allowed by Access-Control-Allow-Headers in preflight response.
这是为什么呢?这个是时候就是我们必须在后端代码配置请求头参数,如下代码
#region #region 跨源(cross-origin)请求中的证书(Credentials)+ 带自定义参数 ////当在ajax设置了withCredentials: true,就是要带域名的cookie,同时这里是不允许返回Access - Control - Allow - Origin: *这个带星号的,这个时候,我们就要设置允许的参数了 app.UseCors(builder => { builder.WithHeaders("authorization", "test", "content-type") //如果开启带检验,并且ajax的headers头部自带自定义参数时。必须带上自定义的 .SetIsOriginAllowed(_ => true) .AllowCredentials(); }); #endregion
这个时候我们看看请求的请求头,如下
我们也要在后端添加上如下几个接受,才是不提示跨域的问题 !!!
当然,如果不想设置参数,我们可以允许所有的头
app.UseCors(builder => { builder.SetIsOriginAllowed(_ => true) .AllowCredentials() .AllowAnyHeader(); });
为了安全我们可以设置固定的域名,来源
app.UseCors(builder => { builder.WithOrigins("http://localhost:5000") .AllowCredentials() .AllowAnyHeader(); });