因为浏览器同源策略,域名协议端口任意一项不同的请求,将不会成功,那需要访问不同域的资源,就需要跨域,本文介绍几种常用的跨域方法原理及实现
- jsonp
- cors
- nginx反向代理
1.jsonp
原理:
浏览器中 <img src='#'> <link href='#'> <script src='#'> 这三个标签请求的资源没有同源策略限制,可以使用script标签请求回来服务器一个js(携带数据),加载之后会立即执行,完成跨域请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> let xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.status == 200) { console.log(xhr.responseText); } } } xhr.open('get', 'http://localhost:80/jsonp?callback=fn', true) xhr.send() function localHandler(res) { console.log('后端数据:', res); } var script = document.createElement('script'); script.src = 'http://localhost:80/jsonp?callback=localHandler'; document.body.appendChild(script) </script> </body> </html>
const Koa = require('koa'); const route = require('koa-route'); const app = new Koa(); app.use(route.get('/jsonp', (ctx)=>{ console.log(ctx.query.callback); let callback = ctx.query.callback ctx.body = callback+"({data: '数据'})" }))
2.CORS
原理:
跨源域资源共享( CORS )机制允许 Web 应用服务器进行跨源访问控制,从而使跨源数据传输得以安全进行,简单来说就是服务端设置响应头来告诉浏览器这些方法和域名端口请求可以访问。
// cors跨域 app.use((ctx, next)=> { console.log('跨域'); ctx.set({ 'Access-Control-Allow-Origin': '*', 'Access-Content-Allow-Methods': 'GET,PUT,POST', 'Access-Content-Expose-Headers': 'Content-Type', // 'Access-Control-Allow-Credentials': true // 设置此字段 Access-Control-Allow-Origin的值不能为 * // }); next() });
3.Nginx反向代理
原理:
简单说一下反向代理,就是我们请求服务器地址的时候,不是直接访问服务器起的服务,而是请求一个代理服务器nginx的域名端口号,这个时候代理服务器将我们的请求转给具体提供服务的服务器群,代理服务器与资源服务器群是一对多的关系,一对一是正向代理,一对多是反向代理;我们要做的是配置nginx服务器配置,设置cors一样的请求头,因为同源策略是浏览器的,所以在代理服务器配置响应头
以下是nginx关键配置:
server { listen 80; server_name localhost; # 前端访问这个域名端口 #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; proxy_pass http://127.0.0.1:3000; # 这是具体的资源服务器
# 以下是添加允许访问的响应头,与cors设置一致
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; add_header Access-Content-Expose-Headers 'Content-Type'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; } }