欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS跨域请求解决方案

程序员文章站 2022-06-02 15:54:00
...

概述

受浏览器同源策略影响, 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
结果:
JS跨域请求解决方案
点击【查询信息】按钮:
提示错误:
JS跨域请求解决方案

三种常用解决方案

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;
    }