1. 跨域学习

1. 跨域学习

1.1 什么是跨域

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实

现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port) 任意一个不同都是不同的域:

如果跨域调用,会出现如下错误:

No ‘Access-Control-Allow-Origin’ header is present on the requested resource.Origin’http://localhost:9100’ is therefore not allowed access. The response had HTTP status code 400.

由于我们采用的是前后端分离的编程方式,前端和后端必定存在跨域问题。解决跨域问题可以采用很多种方案。下面介绍一下常见的解决方案。

1.2 常见跨域解决方案

1. JSONP

原理是:有些标签 script、img、link、iframe … 这些标签不存在跨域请求的限制,就是利用这个特点解决跨域问题。

JSONP 是服务器与客户端跨源通信的常用方法。

优点:简单适用,兼容性好(可以兼容低版本IE),

缺点:只支持 get 请求,不支持 post 请求,导致数据不安全

核心思想:网页通过添加一个 <script> 元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

2.CORS 跨域资源共享
(1) 概念

CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX只能同源使用的限制。整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息有时还会多出一次附加的请求,但用户不会有感觉。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS接口,就可以跨源通信。

请求过程如下图:

image-20230510141444526

Preflight Request(预请求):

image-20230510141740300

不知道大家有没有发现,有时候我们在调用后台接口的时候,会请求两次,如下图。

img

其实第一次发送的就是preflight request(预检请求)。

PreflightResponse(预响应)

然后服务器端给我们返回一个PreflightResponse(预响应)。

image-20230510142611283

预备响应中含有响应头:

Access-Control-Allow-Credentials: true

允许客户端携带验证信息,例如 cookie 之类的。这样客户端在发起跨域请求的时候,就可以携带允许的头,还可以携带验证信息的头。

Access-Control-Allow-Headers: access-control-allow-origin

服务器允许请求中携带字段:access-control-allow-origin

Access-Control-Request-Method:GET,POST,DELETE,PUT 表明服务器允许客户端使用 POST,GET 和 OPTIONS 方法发起请求。

Access-Control-Allow-Origin: http: // localhost:63342

允许进行跨域的地址为 http: // localhost:63342 。 可以在后端配置

Access-Control-Max-Age: 3600

表明该响应的有效时间为3600秒,也就是6分钟。

更多详见技术博客:

https://www.jianshu.com/p/b55086cbd9af

(2) 使用方式呢?

1、后端接口或路由方法上添加@CrossOrigin注解。

① 放在接口上

image-20230510145109356

② 放单个路由方法上:

image-20230510145127193

这种实现方式相当于在路由方法里的响应体中配置响应头:

image-20230510145228744

ps: 想要哪个控制器里的方法跨域,只需将下面代码复制粘贴到该方法里就行。

HttpServletResponse 
    response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
response.addHeader("Access-Control-Allow-Origin","*");

明显这样一个个配置是不行的。

@CrossOrigin(value = "/api",methods = {RequestMethod.POST,RequestMethod.GET})
// value表示允许跨域访问的原始路径  methods表示允许跨域的方法
// 不写就默认全部放开

我们可以使用Spring AOP的思想,对每个请求进行拦截。

③ 给spring注入一个CorsFilter (全局跨域过滤器)的方法实现
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
 
@Configuration
public class AA {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 设置访问源地址
        config.addAllowedOriginPattern("*");
        // 设置访问源请求头
        config.addAllowedHeader("*");
        // 设置访问源请求方法
        config.addAllowedMethod("*");
        // 有效期 1800秒
        config.setMaxAge(1800L);
        // 添加映射路径,拦截一切请求
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        // 返回新的CorsFilter
        return new CorsFilter(source);
    }
 
}
④ WebMvcConfigurer类

重写addCorsMappings方法

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
 
@Configuration
public class CorsConfig implements WebMvcConfigurer {
 
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .allowedHeaders("*")
                .maxAge(3600);
    }
}
3.反向代理

既然不能跨域请求,那么我们不跨域就可以了,通过在请求到达服务器前部署一个服务,将接口请求进行转发,这就是反向代理。通过一定的转发规则可以将前端的请求转发到其他的服务。

通过反向代理我们将前后端项目统一通过反向代理来提供对外的服务,这样在前端看上去就跟不存在跨域一样。

反向代理麻烦之处就在原对 Nginx 等反向代理服务的配置,在目前前后端分离的项目中很多都是采用这种方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值