跨域问题的解决方案

​1.什么是跨域?
当一个页面请求url的协议、域名、端口三者之间任何一者与当前页面url不同即为跨域。举个例子:

当前页面url被请求页面url是否跨域原因
http://www.yzfree.com/http://www.yzfree.com/index.html同源(协议、域名、端口号相同)
http://www.yzfree.com/https://www.yzfree.com/index.html跨域协议不同(http/https)
http://www.yzfree.com/http://www.baidu.com/跨域主域名不同(yzfree/baidu)
http://www.yzfree.com/http://blog.yzfree.com/跨域子域名不同(www/blog)
http://www.yzfree.com:8080/http://www.yzfree.com:8089/跨域端口号不同(8080/8089)

2.为什么会出现跨域问题
出现跨域问题是源于浏览器的同源策略限制的。同源策略(Same origin policy)是一种约定,它是浏览器针对安全功能的一种实现,如果缺少了同源策略,浏览器很容易受到XSS,CSFR等网络攻击。

3.跨域会导致什么问题
不能读取非同源网页中的 Cookie、LocalStorage 等数据
不能接触非同源网页的 DOM 结构
不能向非同源地址发送 AJAX 请求
跨域的现象:
在这里插入图片描述

注意:html有一些特殊标签例如:<img> <script> <link> <frame> 等具有跨域的特性,可以直接访问非同源地址,可放心使用。

4.跨域问题的解决方案
4.1 JSONP

JSONP 的方式就是通过添加一个 script 元素,远程获取 js 代码并执行。
整个逻辑就是:前端向服务器发送请求并指定回调函数为:test ,后端返回 js代码 “test(110)“ ,前端收到并执行
注意:这种方式只只支持get请求。

①原生实现:

<script src="http://yzfree.com/v1?callback=test"></script>
<script type="text/javascript">
    function test(res){
        console.log(res.data);
    }
</script>

② jQuery ajax:

$.ajax({
    url: 'http://yzfree.com/v1',
    type: 'get',
    dataType: 'jsonp', 
    jsonpCallback: "test", 
    data: {}
});

③ Vue.js

this.$http.jsonp('http://yzfree.com/v1', {
    params: {},
    jsonp: 'test'
}).then((res) => {
    console.log(res); 
})

4.2 CORS

CORS 跨域资源分享(Cross-Origin Resource Sharing)的办法是让每一个页面需要返回一个名为Access-Control-Allow-Origin的http头来允许非同源的站点访问
一般请求只需在服务器端设置Access-Control-Allow-Origin,如果是带cookie的跨域请求那么前后端都要进行设置
【前端】

①原生ajax

var xhr = new XMLHttpRequest();
// 设置可以携带cookie
xhr.withCredentials = true;
​
xhr.open('post', 'http://yzfree.com/v1', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=gwx');
​
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
    }
};

② jQuery ajax

$.ajax({
   url: 'http://yzfree.com/v1',
   type: 'get'
  data: {}
  xhrFields: 
      // 设置可以携带cookie
      withCredentials: true
  }
})


③vue-resource

// 设置可以携带cookie
Vue.http.options.credentials = true

④ axios

// 设置可以携带cookie
axios.defaults.withCredentials = true

【后端SpringBoot】
在服务器响应客户端的时候,带上Access-Control-Allow-Origin
① 使用 @CrossOrigin 注解

@RequestMapping("/v1")
@RestController
//@CrossOrigin //不限制指定域名,都可以访问
@CrossOrigin("https://yzfree.com") // 指定域名
public class CorsTestController {
    @GetMapping("/test")
    public String sayHello() {
        return "success";
    }
}

② CORS全局配置

@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 允许任何域名使用
        corsConfiguration.addAllowedHeader("*"); // 允许任何头
        corsConfiguration.addAllowedMethod("*"); // 允许任何方法(post、get等)
        return corsConfiguration;
    }@Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); 
        return new CorsFilter(source);
    }
}

③ 拦截器实现

@Component
public class CorsFilter implements Filter {@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.addHeader("Access-Control-Allow-Credentials", "true");
        res.addHeader("Access-Control-Allow-Origin", "*");
        res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
        res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");
        if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
            response.getWriter().println("ok");
            return;
        }
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

4.3 代理proxy

通过中间件来实现,浏览器有跨域限制,但是服务器没有。如果 changeOrigin 设置为true,那么本地会虚拟一个 node 服务端接收你的请求并转发

proxyTable: {
 '/api': {
  target: '目标地址', //目标地址
  changeOrigin: true, //是否跨域
  pathRewrite: {
   '^/api': '' //路径重写
   }
 }
}//使用axios
 this.$axios.post("/api/gwx",{
   发送的数据
  }).then(data=>{
   console.log(data);
  })

4.4 nginx反向代理

通过修改 nginx.conf 配置文件做代理转发

server {
    listen 80;
    server_name www.yzfree.com;
​
 location ^~/gwx/ {
            proxy_pass http://xxx.com:80;//你要转发的地址
            proxy_set_header Host $host:$server_port;
            proxy_set_header Remote_Addr $remote_addr;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            client_max_body_size    2048m;
        }

以上就是常见的几种跨域解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的架狗师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值