JS跨域请求解决方案
概述
受浏览器同源策略影响, JS默认是不能跨域的
同源策略:简单来讲同源策略就是浏览器为了保证用户信息的安全,防止恶意的网站窃取数据,禁止不同域之间的JS进行交互。对于浏览器而言只要域名、协议、端口其中一个不同就会引发同源策略,从而限制他们之间如下的交互行为:
1.Cookie、LocalStorage和IndexDB无法读取;
2.DOM无法获得;
3.AJAX请求不能发送。
举例来说,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:不同源(端口不同)在这里插入代码片
演示
demo1端口8181
页面
<script type="text/javascript">
function find() {
$.ajax({
url:'http://localhost:8182/abc/find',
type:'get',
dataType:'json',
success:function (data) {
alert(JSON.stringify(data));
}
})
}
</script>
</head>
<body>
<button onclick="find()">查询信息</button>
</body>
demo2端口8182
controller
@RestController
@RequestMapping("/abc")
public class ABCController {
@RequestMapping("/find")
public Map<String, String> find() {
Map<String, String> map = new HashMap<>();
map.put("username", "zhangsan");
map.put("age", "26");
return map;
}
浏览器访问:http://localhost:8182/abc/find
结果:
{
age: "26",
username: "zhangsan"
}
浏览器访问:http://localhost:8181/1.html
结果:
点击【查询信息】按钮:
提示错误:
三种常用解决方案
CORS
CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。
**优点:**官方的,符合标准, 支持所有的请求方式;
**缺点:**受浏览器版本影响 。
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器端。只要服务器端实现了CORS接口,就可以跨源通信。
1.CORS的请求分为两类:
简单请求
非简单请求
只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
凡是不同时满足上面两个条件,就属于非简单请求。
2.简单请求
如果是简单请求的话,会自动在头信息之中,添加一个Origin字段
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
这个Origin对应服务器端的Access-Control-Allow-Origin设置,所以一般来说需要在服务器端加上这个Access-Control-Allow-Origin 指定域名|*
1). 在方法上加入响应头信息
@RequestMapping(value="/find1")
public Map<String,String> find(HttpServletResponse response) throws Exception{
response.setHeader("Access-Control-Allow-Origin","*");
Map<String,String> map = new HashMap<String,String>();
map.put("username", "Tom");
map.put("age", "20");
return map;
}
2). 过滤器实现(定义过滤器)
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
springboot 中配置Filter
@Bean
public FilterRegistrationBean createFilterRegistrationBean(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new CorsFilter());
bean.addUrlPatterns("/*");
bean.setName("corsFilter");
return bean;
}
JSONP
原理 : 通过html中的 <script src="..."></script> 来完成跨域操作 ;
AJAX 无法跨域是受到“同源政策”的限制,但是带有src属性的标签是不受该政策的限制,这也是JSONP方案最核心的原理,就是利用了前端请求静态资源的时候不存在跨域问题这个思路。
**优点:**不受浏览器版本影响(浏览器都支持
JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”。
代码实现:
服务一:8081
<script type="text/javascript">
function find() {
$.ajax({
url:'http://localhost:8182/abc/find1',
type:'get',
dataType:'jsonp',
success:function (data) {
alert(JSON.stringify(data));
}
})
}
</script>
</head>
<body>
<button onclick="find()">查询信息</button>
</body>
服务二:8182
@RestController
@RequestMapping("/abc")
public class ABCController {
@RequestMapping("/find1")
public String find1(String callback) throws JsonProcessingException {
Map<String, String> map = new HashMap<>();
map.put("username", "tom");
map.put("age", "48");
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writeValueAsString(map);
result = callback + "(" + result + ")";
return result;
}
请求路径:Request URL: http://localhost:8182/abc/find1?callback=jQuery111205529669864901734_1576206100598&_=1576206100601
响应数据:jQuery111205529669864901734_1576206100598({"age":"48","username":"tom"})
Proxy
Nginx配置
server {
listen 100;//监听的端口
server_name localhost;
location / {
proxy_pass http://localhost:8182/; //反向代理的转发路径
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true; //是否携带cookie
add_header Access-Control-Allow-Methods 'GET POST'; //支持的请求方式
}
}
ajax请求
<script type="text/javascript">
function find() {
$.ajax({
url:'http://localhost:100/abc/find',
type:'get',
dataType:'json',
success:function (data) {
alert(JSON.stringify(data));
}
})
}
</script>
</head>
<body>
<button onclick="find()">查询信息</button>
</body>
controller
@RestController
@RequestMapping("/abc")
public class ABCController {
@RequestMapping("/find")
public Map<String, String> find() {
Map<String, String> map = new HashMap<>();
map.put("username", "zhangsan");
map.put("age", "26");
return map;
}
上一篇: 凹凸工艺(或击凸名片)在特种纸名片上的应用及注意事项
下一篇: 360浏览器七夕表白神器使用图文教程
推荐阅读
-
CORS(跨域)请求总结和测试
-
Nginx实现AJAX跨域请求图文详解(附代码)
-
JSONP实现跨域请求JSON数据
-
PHP json格式和js json格式 js跨域调用实现代码_PHP教程
-
Springboot 项目源码 vue.js html 跨域 前后分离 shiro权限
-
Springboot html vue.js 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro 权限
-
使用Nginx避免ajax的跨域请求
-
ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践
-
利用SpringMVC解决vue跨域请求
-
PHP Ajax 跨域问题最佳解决方案