Cross Origin Resource Share (CORS)
CORS是一个跨域资源共享方案,为了解决跨域问题,通过增加一系列请求头和响应头,规范安全地进行跨站数据传输
请求头主要包括
请求头 | 解释 |
---|---|
Origin | Origin头在跨域请求或预先请求中,标明发起跨域请求的源域名。 |
Access-Control-Request-Method | Access-Control-Request-Method头用于表明跨域请求使用的实际HTTP方法 |
Access-Control-Request-Headers | Access-Control-Request-Headers用于在预先请求时,告知服务器要发起的跨域请求中会携带的请求头信息 |
with-credentials | 跨域请求携带cookie |
响应头主要包括
响应头 | 解释 |
---|---|
Access-Control-Allow-Origin | Access-Control-Allow-Origin头中携带了服务器端验证后的允许的跨域请求域名,可以是一个具体的域名或是一个*(表示任意域名)。 |
Access-Control-Expose-Headers | Access-Control-Expose-Headers头用于允许返回给跨域请求的响应头列表,在列表中的响应头的内容,才可以被浏览器访问。 |
Access-Control-Max-Age | Access-Control-Max-Age用于告知浏览器可以将预先检查请求返回结果缓存的时间,在缓存有效期内,浏览器会使用缓存的预先检查结果判断是否发送跨域请求。 |
Access-Control-Allow-Methods | Access-Control-Allow-Methods用于告知浏览器可以在实际发送跨域请求时,可以支持的请求方法,可以是一个具体的方法列表或是一个*(表示任意方法)。 |
如何使用
- 客户端只需按规范设置请求头。
- 服务端按规范识别并返回对应响应头,或者安装相应插件,修改相应框架配置文件等。具体视服务端所用的语言和框架而定。
SpringBoot 设置CORS例子
一个spring boot项目中关于CORS配置的一段代码
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
String temp = request.getHeader("Origin");
httpServletResponse.setHeader("Access-Control-Allow-Origin", temp);
// 允许的访问方法
httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, PATCH");
// Access-Control-Max-Age 用于 CORS 相关配置的缓存
httpServletResponse.setHeader("Access-Control-Max-Age", "3600");
httpServletResponse.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept,token");
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
JSONP 跨域
jsonp的原理就是借助HTML中的<script>标签可以跨域引入资源。所以动态创建一个<srcipt>标签,src为目的接口 + get数据包 + 处理数据的函数名。后台收到GET请求后解析并返回函数名(数据)
给前端,前端<script>标签动态执行处理函数
观察下面代码
-
前端代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> var script = document.createElement('script'); script.type = 'text/javascript'; // 传参并指定回调执行函数为getData script.src = 'http://localhost:8080/users?username=xbc&callback=handleData'; document.body.appendChild(script); // 回调执行函数 function handleData(res) { data = JSON.stringify(res) console.log(data); } </script> </body> </html>
-
后端代码(nodejs)
var querystring = require('querystring'); var http = require('http'); var server = http.createServer(); server.on('request', function(req, res) { var params = querystring.parse(req.url.split('?')[1]); var fn = params.callback; // jsonp返回设置 res.writeHead(200, { 'Content-Type': 'text/javascript' }); var data = { user: 'xbc', password: '123456' } res.write(fn + '(' + JSON.stringify(data) + ')'); res.end(); }); server.listen('8080'); console.log('Server is running at port 8080...');
在该例子中,前台收到的res是这样的
前端页面是这样的