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;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值