什么是跨域?
url是由:协议、域名、端口号、资源路径4部分组成
当我们请求一个url时,协议、域名、端口三者之间任意一个与当前页面url不同就是跨域
例如 我们在http://localhost:8080/login
下请求http://localhost:8088/login
这就是跨域请求,这里是因为端口号不同。
是什么原因导致的呢?
同源策略
同源指的是同一个协议、域名、端口。
它是一种约定,是浏览器最核心也是最基本的安全功能,如果缺少同源策略浏览器的正常功能会受到影响。可以web是构建在同源策略的基础之上,浏览器只是对同源策略的一种实现,同源策略会阻止一个域的js脚本和另外一个域的内容进行交互。
非同源限制
- 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
- 无法获取非同源网页的 DOM
- ajax请求不能发送
如何解决
- JSONP
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求。
通过浏览器标签去请求api,避开跨域问题,比如通过’<ima src="xxx"> <script src="xxx">
标签来获取数据,然后通过一个回调函数来把数据进行解析,然后使用数据
原生实现:
<script src="http://localhost/data?callback=getData"></script>
// 获取服务器返回回调函数的数据
<script type="text/javascript">
function getData(res){
// 获得数据
console.log(res.data)
//进行处理
}
</script>
jquery中的ajax:
$.ajax({
url: 'http://localhost/data?callback=getData',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "getData", // 自定义回调函数名
});
- CORS
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,它由一系列传输的[HTTP头]组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。
- 普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
- 其他跨域可根据实际设置
Access-Control-Allow-Origin
指示请求的资源能共享给哪些域。Access-Control-Allow-Credentials
指示当请求的凭证标记为 true 时,是否响应该请求。Access-Control-Allow-Headers
用在对预请求的响应中,指示实际的请求中可以使用哪些 HTTP 头。Access-Control-Allow-Methods
指定对预请求的响应中,哪些 HTTP 方法允许访问请求的资源。Access-Control-Expose-Headers
指示哪些 HTTP 头的名称能在响应中列出。Access-Control-Max-Age
指示预请求的结果能被缓存多久。Access-Control-Request-Headers
用于发起一个预请求,告知服务器正式请求会使用那些 HTTP 头。Access-Control-Request-Method
用于发起一个预请求,告知服务器正式请求会使用哪一种 HTTP 请求方法。
Origin
指示获取资源的请求是从什么域发起的。
asp.netCore中进行配置
可以通过中间件来配置
下载程序包Microsoft.AspNetCore.Cors
在startup中添加
ConfigureContainer
#region 支持跨域
services.AddCors(option =>
option.AddPolicy("AllowCors", _build => _build.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod().AllowCredentials().WithOrigins("http://localhost:8080", "http://localhost:8081")
));
#endregion
Configure
app.UseCors("AllowCors");
最好放在app.UseRouting()之后
如果配置了AllowCredentials()
在前端请求时则可以加上withCredentials: true
如果未配置
则不能加上withCredentials: false
只能是false
withCredentials = true时,必须在后端增加 response 头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为*。
如何配置withCredentials
jquery中的ajax
$.ajax({
url: 'http://localhost/data',
type: 'get',
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
});
axios中设置
axios.defaults.withCredentials = true