小村村长

导航

跨域,以及全部解决方案

一、跨域问题产生的前提条件--必须有浏览器,没有浏览器就没有跨域问题

跨域问题是浏览器为了解决 一些安全问题而提出的一个解决方案:同源策略,

服务器之间的访问是不存在跨域问题的;

二、什么叫同源?

浏览器里面的一个url地址:

https://127.0.0.1:8080/user, 包含 协议(https)、域名主机(127..0.0.1)、端口号:8080,、uri(/user) 四个部分,前面三部分 必须保持完全一样,这个叫浏览器的同源策略;

三、举个栗子

1.我打开了一个www.baidu.com,在页面放一个异步ajax请求到谷歌,即,在我的页面上,调用谷歌的接口,这个请求就会被浏览器拦截下来。

那么问题来了,为什么要有同源策略呢?再举个栗子。。。

假如有个浏览器,打开了2个标签,分别访问了 a网站和b网站,a网站如果向b网站发送ajax请求,并且带上了b网站的cookie,那么就能获取b网站的状态

如下图,基于同源策略每个网站都有自己独立的cookie.并且都是相互隔离的

四、解决跨域的几种常见方法

1.被请求方后端解决:被跨域请求的一方的服务器,设置响应头,支持数据接口的跨域传递 

 

 respones.addHeader("Access-Control-Allow-origin","请求方的url,*代表所有人都可以跨域请求")
 respones.addHeader("Access-Control-Max-age","10秒内")
 respones.addHeader("Access-Control-Allow-Method","GET")
 respones.addHeader("Access-Control-Allow-Headers","xxx")

 

2.SpringBoot解决跨域问题的两种方案:

a、通过给方法或者类加注解的形式,@CrossOrigin。

b、继承接口,重写addCorsMappings方法。

第一种方式:

@RestController
@CrossOrigin("http://localhost:8081")//制定来源。可以写成*表示所有的来源
public class BaseController {
 
 @GetMapping("/hello")
 public String testGet(){
 
  return "get";
 }
 
 @PutMapping("/doPut")
 public String testPut(){
  return "put";
 }
}

第二种方式:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

 @Override
 public void addCorsMappings(CorsRegistry registry) {
  registry.addMapping("/**").allowedOrigins("http://localhost:8081")//同样这里也可以写成*表示所有的来源
    .allowedHeaders("*")
    .allowedMethods("*")
    .maxAge(30*1000);
 }
}

注意点:

路径来源的写法问题:localhost 和127.0.0.1 在Springboot中表示的是不同的字符串,校验会有异常

如果后台指定路径来源为:http://localhost:8081

那么在浏览器里访问前端页面的时候,必须用 http://localhost:8081,不可以写成127.0.0.1或者本机ip地址。否则还是会报跨域错误。

 

3.我用我自己的服务器去请求,绕过浏览器的同源策略--  反向代理

  a网站的网页上想要拿到b网站的数据,

 

  我后端拦截了一个a网站的跨域的请求,用我的a网站后端服务器代替浏览器去请求b网站,后端进行交互,后端服务器拿到数据后

4.nginx静态服务器,反向代理--在前端解决跨域

  网页a,访问自己域里面的nginx代理服务器中的资源,代理服务器后端转发到b服务器里面去,拿到数据给网页a;

配置反向代理:

nginx 目录:conf->nginx.conf

server {
    listen       443;
    server_name  www.baidu.com;  //在这个服务器上 443 端口只要有请求进来,就进行下面的重定向
    
    location / {  //只要匹配到 / 的uri就跳转到下面这个地址
        //用于处理uri不一致的情况,假如原生请求 是  127.0.0.1:8081/api/user
//转发到127.0.0.1:8082/user,把路径上的地址api去除掉
        rewrite  ^api/(.*)$ /$1 break;
        proxy_pass   https://www.google.com:443;
        proxy_connect_timeout 600;
        proxy_read_timeout 5000;
    }

/**下面是缺省值*/

     location / {   //只要匹配到/d的,就跳转到 下面这个页面
          root html;
          index index.html index.htm;
     }


}

 

5.jsonP。最古老的方式

 利用了浏览器里面的一些标签,天然支持跨域

//这个是a网站 127.0.0.1:8081 页面a.html中的一个方法,
<script>
function cross(data){
console.log(data)
}
</script>

<script src ="http://127.0.0.1:8082/cross"></script> //只支持get请求
@RequestMapping("/cross")
public String cross(HttpServletResponse response){

      return "cross(123)";
}

加载a.html-->访问 “http://127.0.0.1:8082/cross”-->返回了给a.html :"cross(123)”字符串-->a.html 执行了  cross(123),相当于执行了 ,function cross(data){ console.log(123)}->拿到123数据;  

只能支持get请求,标签不好发post请求,不像表单,你能发post请求;

总结:

跨域解决实际上有:3种方式:

1.目标服务器支持跨域

2.浏览器访问本机服务器,然后内部对跨域请求进行转发

3.利用html的部分标签支持跨域特点进行跨域get请求访问

 

 

 

 

 

 

 

 

 

,

 

posted on 2022-04-24 23:42  小村村长  阅读(395)  评论(0编辑  收藏  举报