起源:
错误是由于CORS跨域验证机制设置不正确导致的,但是上面的这个错误我得解决呀,不好办吗,本文结合各大……(广告时间)能说明白当然是不可能了,还需要点开文中链接看一看、瞧一瞧,当然偶尽量在本文中写滴清楚
这个前言让他有点特别吧,先写一下出现的几种问题:
No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 404
原因:(解决:后端允许options请求)
No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 405
原因:(后端关闭对应的安全配置)
安全配置
),阻止了OPTIONS请求
No 'Access-Control-Allow-Origin' header is present on the requested resource,并且status 200
原因:(后端增加对应的头部支持)
heade contains multiple values '*,*'
原因:
正文:
浏览器安全的基石是"同源政策"(same-origin policy)
跨域:浏览器不能执行其他网站的脚本,由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制;
【源】
协议、域名、端口相同;
http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)
http://www.example.com/dir2/other.html
:同源http://example.com/dir/other.html
:不同源(域名不同)http://v2.www.example.com/dir/other.html
:不同源(域名不同)http://www.example.com:81/dir/other.html
:不同源(端口不同)保证用户信息的安全,防止恶意的网站窃取数据,这个文章的有两个例子,助于理解,其实挺好理解的
如果非同源,共有三种行为受到限制:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
跨域请求、ajax技术提高页面体验同时带来安全隐患,如CSRF(cross-site request forgery)
通过伪装来自受信任用户的请求来利用受信息的网站(一起慢慢读)
1、验证http referer字段
http头有referer字段,记录请求来源地:简单易行但值由浏览器提供,不安全
2、请求地址中添加token并验证
对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来说,要在 form 的最后加上
但对每个请求加很麻烦易漏,难保证token本身安全;GET 请求不需要 CSRF Token(因为写操作不应该用 GET),POST 请求在执行写操作時依旧需要 CSRF Token
3、http头中自定义属性并验证
将token放到http头自定义属性中,通过xmlHttpRequest类一次性给all请求加上csrftoken头属性将token放入其中
xmlhttprequest常用于ajax对页面局部的异步刷新,不是all请求都适合发起,且得到的页面不能被浏览器记录
HTML标签里,一些标签比如script、img这样的获取资源的标签(all拥有”src”这个属性的标签)没有跨域限制的
1、json是数据交换格式,纯文本、跨平台、轻量、可读、易编写解析,JavaScript支持,almost后端语言支持
格式:{一组“不同类型的无序键值对集合”}[一组“相同类型的有序数据集合”] :映射符 ,分隔符 ""定义符(字符串必须用“”引起)
2、jsonp:一种非官方跨域数据交互协议;web客户端通过调用脚本的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀)
用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了;
不再直接把远程js文件写死,而是编码实现动态查询:callback标识:我想要一段调用XXX函数的js代码,请你返回给我,服务器安装需求生成响应
前端可以用ajax实现,后端大概是这个样子,取出callback包装一下返回值【这个博客里面也有例子】
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//数据
List studentList = getStudentList();
JSONArray jsonArray = JSONArray.fromObject(studentList);
String result = jsonArray.toString();
//前端传过来的回调函数名称
String callback = request.getParameter("theFunction");
//用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
result = callback + "(" + result + ")";
response.getWriter().write(result);
支持所有类型的HTTP请求
看到这个是不是有些熟悉,@CrossOrigin有没有用过,需要客户端和服务器同时支持
估计我这里是服务器不支持的原因,每个方法都加了注解,项目加了过滤器、拦截器都不行,诶~宝宝的小心脏
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)【源】
对于简单请求, 浏览器可以自行解决其中的跨域问题. 例如我们熟知的一个跨域通信的解决方式JSON-P
就是利用GET发送一个简单请求来规避跨域的问题.HTML中的表单提交也不需要处理跨域问题.【源】(其实form是不需要处理的,下面会说,而且实践通过咯)
任何不符合上述条件的请求都算作非简单请求, 浏览器在处理非简单的跨域请求时会与服务器进行额外的通信(称之为预检请求)
浏览器直接发出CORS请求:头信息之中,增加一个Origin
字段
说明本次请求来自哪个源(协议 + 域名 + 端口)服务器根据这个值,决定是否同意这次请求
如果源不在许可范围内,服务器会返回正常的http响应但头信息中无Access-Control-Allow-Origin,抛错被XMLHttpRequest
的onerror
回调函数捕获;在许可范围,返回响应多出几个头信息字段:
//请求时origin字段的值,*表示接受任意域名的请求
Access-Control-Allow-Origin: http://api.bob.com
//可选,Boolean值,是否容许发送cookie;true 服务器许可 可包含在请求中发给服务器、只能设为true,如果服务器不要浏览器发cookie,删除字段即可
Access-Control-Allow-Credentials: true
//可选,cors请求时,xmlhttprequest的getResponseHeader拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers,下面可返回“FooBar”字段的值
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8//泥萌猜
CORS请求默认不发送Cookie和HTTP认证信息,如果要把Cookie发到服务器,一方面要服务器同意,指定Access-Control-Allow-Credentials字段,另一方面,开发者必须在AJAX请求中打开withCredentials属性
var xhr = new XMLHttpRequest(); xhr.withCredentials = true;
$.post({
url: ‘1747937498.PHP’,
data: {
appId: appId
},
dataType: "json",
timeout:300000,
xhrFields:{withCredentials: true},
success: function (result) {
},
error: function () {
}
});
要发送Cookie,Access-Control-Allow-Origin
就不能设为星号,指定明确的、与请求网页一致的域名
指种对服务器有特殊要求的请求,比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错。
var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
//请求的方法是PUT
xhr.open('PUT', url, true);
//发送一个自定义头信息X-Custom-Header
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
"预检"请求用的请求方法是OPTIONS
,表示这个请求是用来询问的
1、头信息里面,关键字段Origin同上
2、Access-Control-Request-Method:浏览器的CORS请求会用到哪些HTTP方法
3、Access-Control-Request-Headers:逗号分隔的字符串,CORS请求会额外发送的头信息字段
预检请求的回应:
请求中Access-Control-Allow-Origin: http://api.bob.com或*表示可以请求
如果否定,返回正常http回应,无cors相关头信息,浏览器触发错误 同上
1、Access-Control-Allow-Methods:服务器支持的所有跨域请求的方法,避免多次预检请求
2、Access-Control-Allow-Headers:请求包括则该字段必需,支持的all头信息字段
3、Access-Control-Allow-Credentials
4、Access-Control-Max-Age:本次预检请求有效期,s
参考:
什么是跨域?解决跨域的五种方法。
阮一峰大佬 跨域资源共享 CORS 详解
撒网要见鱼 https://segmentfault.com/a/1190000012469713
Hosee CORS与CSRF https://my.oschina.net/hosee/blog/903665
https://www.cnblogs.com/chiangchou/p/jsonp.html jQuery jsonp 跨域请求
http://www.ruanyifeng.com/blog/2016/04/cors.html 跨域资源共享 CORS 详解
https://kb.cnblogs.com/page/139725/ 说说JSON和JSONP,也许你会豁然开朗
https://segmentfault.com/a/1190000015597029 这个链接失效了,奇怪 点不开
https://www.imooc.com/article/19869?block_id=tuijian_wz 一篇文章可以解决跨域