js跨域问题的三种解决方案
2018-03-01 11:19
561 查看
概述
跨域问题在分布式应用中经常会遇到,这里仅仅介绍跨域的三种解决方案,对跨域的概念及原因不做解释,感兴趣的朋友可以网上自行百度。Nginx代理
这种方式比较简单,将A应用和B应用都通过一个统一的地址进行转发,这样就可以避免跨域问题出现。server {listen 80;
server_name www.gameloft9.top;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /manager {
proxy_pass http://127.0.0.1:6108/manager; proxy_set_header Host $http_host;
}
location /service {
proxy_pass http://127.0.0.1:9200/service; proxy_set_header Host $http_host;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
}在上面的配置中,manager和service属于不同的域(IP虽然一样,但是端口不一样),如果manger里面的js调用service里面的接口,会报跨域错误。通过nginx转发后,所有的域都映射到www.gameloft9.top了,然后通过/manager,/service分别转发到各自的应用中,巧妙的避免了跨域问题。如果是纯前端项目,可以直接托管到nginx里面,也可以解决跨域问题,原理一样。
JSONP
因为<script>标签不受跨域限制,因此在此基础上出现了JSONP的ajax请求方式。通过包装一个<script>标签,去请求接口,然后返回数据及回调函数,这样就达到了跨域的目的。/*** 测试JSONP跨域请求
* */
function testJsonP() {
$.ajax({
url: root + "/testjsonp.do",
type: "GET",//jsonp只支持GET请求
data: request,
dataType: "jsonp",
jsonp: "callback",//指定查询字符串中回调方法key
jsonpCallback: "print",//指定查询字符串中回调方法value,例如callback=print
success: function (data) {//返回的是回调方法的入参
//alert(data)
}
})
}JSONP的请求方式,需要设置dataType为"jsonp",表明这是一个jsonp的请求,jsonp是指定查询字符串中回调函数的参数的名称,jsonpCallback指定的是查询字符串中回调的函数名。一个标准的jsonp的请求如下所示:http://localhost:8080/demo/testjsonp.do?callback=print&number=2&_=1519870989148jsonp只支持get请求,所有的参数都会转化为查询字符串,然后再补上回调函数的参数(就是这里的callback=print),如果jsonpCallback没有指定,jQuery会自动生成一个随机的函数名称,例如:
Query17208297070672462461_1491991295320当然我们不建议这么做。
后台处理如下:/**
* 测试ajax josnp跨域请求
* */
@RequestMapping(value = "/testjsonp.do", method = RequestMethod.GET)
//@ResponseBody
public void test(Model model,String callback,String number, HttpServletRequest request,HttpServletResponse response)throws Exception{
//如果是spring mvc,启用了@ResponseBody注解,可以直接返回调用语句
//return callback+"("+result.toString()+")";
Integer result = Integer.parseInt(number);
result = result*result;//计算平方值
Writer client = response.getWriter();
client.write(callback+"("+result.toString()+")");
client.flush();
}后台接受到参数后,进行业务逻辑调用,并把结果塞进回调函数中,返回即可。
设置Access-Control-Allow-*头
jsonp的方式虽然简便,但有个缺点,就是只支持get请求,对于只支持post的接口就不支持了。通过后台设置Access-Control-*等header,可以解决跨域问题,而且get,post都支持。/*** 测试ajax 设置head跨域请求
* */
@RequestMapping(value = "/testCrossOrigin.do", method = RequestMethod.POST)
@ResponseBody
public String crossOrigin(Model model,String number,HttpServletRequest request,HttpServletResponse response)throws Exception{
//设置response header,允许跨域请求
response.setHeader("Access-Control-Allow-Origin","*");
response.setHeader("Access-Control-Allow-Methods","POST");
response.setHeader("Access-Control-Allow-Headers","x-requested-with,content-type");
response.setHeader("Access-Control-Allow-Max-Age","1728000");//单位:秒,这里是20天
Integer result = Integer.parseInt(number);
result = result*result;
return result.toString();
}Access-Control-Allow-Origin设置允许跨域的白名单,在白名单里的跨域请求是允许的。
Access-Control-Allow-Methods设置接受的方法,这里只接受POST方法。
Access-Control-Allow-Headers设置接受的请求头,用逗号分隔。
Access-Control-Allow-Max-Age设置预检的有效期,单位为秒。发送正式请求前,浏览器会预先发送一个预检请求,如果服务器返回了上述信息,表明是可以跨越请求的,然后才会正式发送请求。预检成功后,在有效期内就不用再发送了。
运行截图
工程地址:https://github.com/gameloft9/cors-demo
参考文章:1-跨域资源共享CORS详解
2-cors
相关文章推荐
- angular.js中解决跨域问题的三种方式
- Ajax跨域问题有三种解决方案
- ajax跨域问题(三种解决方案)
- js跨域问题及解决方案
- js 跨域问题以及解决方案
- js跨域问题 常见的集中解决方案
- NODE.JS跨域问题的完美解决方案
- JS 跨域问题和解决方案
- js跨域问题解释 解决方案值使用jsonp或jQuery
- 5种处理js跨域问题方法汇总
- 详解js跨域原理以及2种解决方案
- PHP Ajax 跨域问题最佳解决方案
- 原生JS解决跨域问题
- 服务器端解决跨域问题的三种方法
- 关于session过期返回主页解决方案之一以及js中的“和'使用问题
- js跨域问题浅析及解决方法优缺点对比
- 解决js跨域的问题
- 四种JS跨域解决方案及其实现原理
- 基于Node.js的socket.io机制的陷阱,仅针对于客户端继承socket.io的问题的解决方案
- js跨域及解决方案